Decompiled source of CrewLateJoin v1.0.2

CrewLateJoin.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("CrewLateJoin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("FluxTeam")]
[assembly: AssemblyProduct("CrewLateJoin")]
[assembly: AssemblyCopyright("Copyright © FluxTeam 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8f3d5e42-1c9f-4a8b-9e2d-5c1a8b3d9e4f")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.2.0")]
namespace CrewLateJoin;

[BepInPlugin("FluxTeam.CrewLateJoin", "Crew Late Join", "1.0.2")]
public class CrewLateJoin : BaseUnityPlugin
{
	private const string GUID = "FluxTeam.CrewLateJoin";

	private const string NAME = "Crew Late Join";

	private const string VERSION = "1.0.2";

	internal static ManualLogSource logger;

	internal static CrewLateJoin instance;

	public static ConfigEntry<bool> AllowLateJoin;

	public static ConfigEntry<bool> EnableCartDurationChanges;

	public static ConfigEntry<float> CartStayDuration;

	private void Awake()
	{
		//IL_00de: 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_0110: Expected O, but got Unknown
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Expected O, but got Unknown
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Expected O, but got Unknown
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Expected O, but got Unknown
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Expected O, but got Unknown
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_021f: Expected O, but got Unknown
		logger = ((BaseUnityPlugin)this).Logger;
		instance = this;
		AllowLateJoin = ((BaseUnityPlugin)this).Config.Bind<bool>("Network.Room", "AllowLateJoin", true, "Allow players to join the room even after the game has started");
		EnableCartDurationChanges = ((BaseUnityPlugin)this).Config.Bind<bool>("Network.Cart", "EnableCartDurationChanges", false, "Enable custom cart stay duration. When disabled, uses vanilla stay duration.");
		CartStayDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Network.Cart", "CartStayDuration", 90f, "How long the cart stays in seconds. Only used if EnableCartDurationChanges is true. Vanilla default is 90s.");
		logger.LogInfo((object)"Crew Late Join v1.0.2 loaded!");
		logger.LogInfo((object)$"Config - Allow Late Join: {AllowLateJoin.Value}");
		logger.LogInfo((object)$"Config - Cart Duration Changes: {EnableCartDurationChanges.Value}, Duration: {CartStayDuration.Value}s");
		try
		{
			Harmony val = new Harmony("FluxTeam.CrewLateJoin");
			MethodInfo methodInfo = AccessTools.Method(typeof(GameController), "StartNewMapRPC", (Type[])null, (Type[])null);
			HarmonyMethod val2 = new HarmonyMethod(typeof(GameControllerPatches), "StartNewMapRPC_Prefix", (Type[])null);
			HarmonyMethod val3 = new HarmonyMethod(typeof(GameControllerPatches), "StartNewMapRPC_Postfix", (Type[])null);
			val.Patch((MethodBase)methodInfo, val2, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(GameController), "GoToCheckpointRPC", (Type[])null, (Type[])null);
			HarmonyMethod val4 = new HarmonyMethod(typeof(GameControllerPatches), "GoToCheckpointRPC_Postfix", (Type[])null);
			val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(GameController), "ResetGameRPC", (Type[])null, (Type[])null);
			HarmonyMethod val5 = new HarmonyMethod(typeof(GameControllerPatches), "ResetGameRPC_Postfix", (Type[])null);
			val.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, val5, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			ItemCarrierPatches.InitializeReflection();
			MethodInfo methodInfo4 = AccessTools.Method(typeof(ItemCarrierController), "Start", (Type[])null, (Type[])null);
			HarmonyMethod val6 = new HarmonyMethod(typeof(ItemCarrierPatches), "Start_Postfix", (Type[])null);
			val.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, val6, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			MethodInfo methodInfo5 = AccessTools.Method(typeof(ItemCarrierController), "Update", (Type[])null, (Type[])null);
			HarmonyMethod val7 = new HarmonyMethod(typeof(ItemCarrierPatches), "Update_Prefix", (Type[])null);
			val.Patch((MethodBase)methodInfo5, val7, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			logger.LogInfo((object)"Harmony patches applied successfully");
		}
		catch (Exception arg)
		{
			logger.LogError((object)$"Failed to apply Harmony patches: {arg}");
		}
	}
}
public static class GameControllerPatches
{
	public static void StartNewMapRPC_Prefix()
	{
		if (CrewLateJoin.AllowLateJoin.Value && PhotonNetwork.IsMasterClient)
		{
			CrewLateJoin.logger.LogInfo((object)"AllowLateJoin Enabled - Photon Room will be reopened after StartNewMapRPC");
		}
	}

	public static void StartNewMapRPC_Postfix()
	{
		if (PhotonNetwork.IsMasterClient && CrewLateJoin.AllowLateJoin.Value)
		{
			CrewLateJoin.logger.LogInfo((object)"AllowLateJoin Enabled - Forcing Photon Room to stay Open (IsOpen = true)");
			PhotonNetwork.CurrentRoom.IsOpen = true;
			PhotonNetwork.CurrentRoom.IsVisible = true;
		}
	}

	public static void GoToCheckpointRPC_Postfix()
	{
		if (PhotonNetwork.IsMasterClient && CrewLateJoin.AllowLateJoin.Value)
		{
			PhotonNetwork.CurrentRoom.IsOpen = true;
		}
	}

	public static void ResetGameRPC_Postfix()
	{
		if (PhotonNetwork.IsMasterClient && CrewLateJoin.AllowLateJoin.Value)
		{
			PhotonNetwork.CurrentRoom.IsOpen = true;
		}
	}
}
public static class ItemCarrierPatches
{
	private static FieldInfo _arriveTimerField;

	private static FieldInfo _departTimerField;

	private static FieldInfo _itemsField;

	private static FieldInfo _stateField;

	private static FieldInfo _stayDurationField;

	private static FieldInfo _animatorField;

	private static FieldInfo _speedField;

	private static FieldInfo _crankSpeedField;

	private static FieldInfo _maxCrankSpeedField;

	private static FieldInfo _wheelSpeedField;

	private static FieldInfo _maxWheelSpeedField;

	private static FieldInfo _frontAxleField;

	private static FieldInfo _backAxleField;

	private static int _lastLoggedState = -1;

	private static bool _hasAppliedDuration = false;

	public static void InitializeReflection()
	{
		CrewLateJoin.logger.LogInfo((object)"Initializing ItemCarrier reflection fields...");
		_arriveTimerField = AccessTools.Field(typeof(ItemCarrierController), "arriveTimer");
		_departTimerField = AccessTools.Field(typeof(ItemCarrierController), "departTimer");
		_itemsField = AccessTools.Field(typeof(ItemCarrierController), "items");
		_stateField = AccessTools.Field(typeof(ItemCarrierController), "state");
		_stayDurationField = AccessTools.Field(typeof(ItemCarrierController), "stayDuration");
		_animatorField = AccessTools.Field(typeof(ItemCarrierController), "animator");
		_speedField = AccessTools.Field(typeof(ItemCarrierController), "speed");
		_crankSpeedField = AccessTools.Field(typeof(ItemCarrierController), "crankSpeed");
		_maxCrankSpeedField = AccessTools.Field(typeof(ItemCarrierController), "maxCrankSpeed");
		_wheelSpeedField = AccessTools.Field(typeof(ItemCarrierController), "wheelSpeed");
		_maxWheelSpeedField = AccessTools.Field(typeof(ItemCarrierController), "maxWheelSpeed");
		_frontAxleField = AccessTools.Field(typeof(ItemCarrierController), "frontAxle");
		_backAxleField = AccessTools.Field(typeof(ItemCarrierController), "backAxle");
		CrewLateJoin.logger.LogInfo((object)"ItemCarrier reflection fields initialized");
	}

	public static void Start_Postfix(ItemCarrierController __instance)
	{
		if (!((Object)(object)__instance == (Object)null) && !(_stayDurationField == null))
		{
			float num = (float)_stayDurationField.GetValue(__instance);
			ConfigEntry<bool> enableCartDurationChanges = CrewLateJoin.EnableCartDurationChanges;
			if (enableCartDurationChanges != null && enableCartDurationChanges.Value && !_hasAppliedDuration)
			{
				float num2 = CrewLateJoin.CartStayDuration?.Value ?? num;
				_stayDurationField.SetValue(__instance, num2);
				_hasAppliedDuration = true;
				CrewLateJoin.logger.LogInfo((object)$"Applied custom cart stay duration: {num2}s (vanilla: {num}s)");
			}
		}
	}

	private static bool ShouldApplyCustomLogic()
	{
		if (!CrewLateJoin.AllowLateJoin.Value)
		{
			return false;
		}
		if ((Object)(object)SurfaceGenerator.instance != (Object)null && SurfaceGenerator.instance.traveling)
		{
			return false;
		}
		if ((Object)(object)GameController.instance != (Object)null && !GameController.instance.atCheckpoint)
		{
			return true;
		}
		return false;
	}

	public static bool Update_Prefix(ItemCarrierController __instance)
	{
		PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
		if ((Object)(object)component == (Object)null)
		{
			return true;
		}
		if (!component.IsMine)
		{
			UpdateVisuals(__instance);
			return false;
		}
		if (!ShouldApplyCustomLogic())
		{
			return true;
		}
		UpdateCartLogic(__instance, component);
		UpdateVisuals(__instance);
		return false;
	}

	private static void UpdateCartLogic(ItemCarrierController instance, PhotonView pv)
	{
		float num = (float)_arriveTimerField.GetValue(instance);
		float num2 = (float)_departTimerField.GetValue(instance);
		IList list = _itemsField.GetValue(instance) as IList;
		int num3 = (int)_stateField.GetValue(instance);
		num -= Time.deltaTime;
		num2 -= Time.deltaTime;
		_arriveTimerField.SetValue(instance, num);
		_departTimerField.SetValue(instance, num2);
		if (num <= 0f && list.Count > 0 && num3 == 0)
		{
			pv.RPC("ArriveRPC", (RpcTarget)0, Array.Empty<object>());
			if (num3 != _lastLoggedState)
			{
				CrewLateJoin.logger.LogInfo((object)"Cart arriving (AllowLateJoin fix active)");
				_lastLoggedState = 1;
			}
		}
		if (num3 == 2 && ((bool)AccessTools.Method(typeof(ItemCarrierController), "AllItemsTaken", (Type[])null, (Type[])null).Invoke(instance, null) || num2 <= 0f))
		{
			pv.RPC("DepartRPC", (RpcTarget)0, Array.Empty<object>());
			if (num3 != _lastLoggedState)
			{
				CrewLateJoin.logger.LogInfo((object)"Cart departing (AllowLateJoin fix active)");
				_lastLoggedState = 3;
			}
		}
	}

	private static void UpdateVisuals(ItemCarrierController instance)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Expected O, but got Unknown
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		Animator val = (Animator)_animatorField.GetValue(instance);
		float num = (float)_speedField.GetValue(instance);
		float num2 = (float)_crankSpeedField.GetValue(instance);
		float num3 = (float)_maxCrankSpeedField.GetValue(instance);
		float num4 = (float)_wheelSpeedField.GetValue(instance);
		float num5 = (float)_maxWheelSpeedField.GetValue(instance);
		Transform val2 = (Transform)_frontAxleField.GetValue(instance);
		Transform val3 = (Transform)_backAxleField.GetValue(instance);
		val.SetFloat("Speed", Mathf.Clamp(num * num2, 0f - num3, num3));
		((Component)val2).transform.Rotate(Vector3.up * (0f - Mathf.Min(num, num5)) * num4 * Time.deltaTime);
		((Component)val3).transform.Rotate(Vector3.up * Mathf.Min(num, num5) * num4 * Time.deltaTime);
	}
}