Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ArenaRaceMultiplayerSpawnFix v4.0.2
ArenaRaceMultiplayerSpawnFix.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; 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 HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOJP.ArenaRaceMultiplayerSpawnFix { [BepInPlugin("REPOJP.ArenaRaceMultiplayerSpawnFix", "ArenaRaceMultiplayerSpawnFix", "4.0.2")] public class ArenaRaceMultiplayerSpawnFixPlugin : BaseUnityPlugin { private sealed class LayoutPlan { public readonly List<Vector3> Positions = new List<Vector3>(); } [HarmonyPatch(typeof(LevelGenerator), "PlayerSpawn")] private static class LevelGeneratorPlayerSpawnPatch { private static void Postfix() { try { ScheduleLayoutApplyFromPlayerSpawn(); } catch (Exception ex) { LogError("Failure: PlayerSpawn Postfix\n" + ex); } } } [HarmonyPatch(typeof(ArenaRace), "StateSetRPC")] private static class ArenaRaceStateSetRPCPatch { private static void Postfix(ArenaRace __instance, States _state) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 try { if ((int)_state == 2) { ApplyStartBoostOnce(__instance); } } catch (Exception ex) { LogError("Failure: ArenaRace.StateSetRPC Postfix\n" + ex); } } } [CompilerGenerated] private sealed class <DelayedApplyLayoutCoroutine>d__31 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int scheduleId; private int <attempt>5__1; private string <waitReason>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedApplyLayoutCoroutine>d__31(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <waitReason>5__2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <attempt>5__1 = 1; break; case 1: <>1__state = -1; if (scheduleId != layoutScheduleId) { return false; } if (!CanApplyLayoutNow(out <waitReason>5__2)) { if (<attempt>5__1 == 45) { LogWarning("Skipped layout apply after retry: " + <waitReason>5__2 + " | Attempts=" + <attempt>5__1 + " | " + BuildContextSummary()); } <attempt>5__1++; break; } TryApplyLayout(scheduleId, <attempt>5__1); return false; } if (<attempt>5__1 <= 45) { <>2__current = null; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "REPOJP.ArenaRaceMultiplayerSpawnFix"; public const string PluginName = "ArenaRaceMultiplayerSpawnFix"; public const string PluginVersion = "4.0.2"; private const float FixedHorizontalSpacing = 0.8f; private const float FixedVerticalSpacing = 3f; private const float FixedHeightOffset = 5f; private const float FixedBackwardOffset = 10f; private static ManualLogSource logSource; private static Harmony harmony; private static ArenaRaceMultiplayerSpawnFixPlugin pluginInstance; private static ConfigEntry<bool> enabledConfig; private static ConfigEntry<int> horizontalPlayersConfig; private static ConfigEntry<int> verticalPlayersConfig; private static ConfigEntry<bool> startBoostEnabledConfig; private static ConfigEntry<float> startBoostMultiplierConfig; private static FieldInfo arenaRacePlayerVehicleMapField; private static FieldInfo arenaRaceVehiclesField; private static MethodInfo itemVehicleOverrideYawMethod; private static MethodInfo itemVehicleOverridePitchMethod; private static MethodInfo playerAvatarSpawnRPCMethod; private static int lastStartBoostArenaRaceInstanceId; private static int layoutScheduleId; private static bool layoutApplyInProgress; private const int DelayedLayoutMaxAttempts = 45; private void Awake() { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown try { ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); pluginInstance = this; logSource = ((BaseUnityPlugin)this).Logger; BindConfig(); arenaRacePlayerVehicleMapField = AccessTools.Field(typeof(ArenaRace), "playerVehicleMap"); arenaRaceVehiclesField = AccessTools.Field(typeof(ArenaRace), "vehicles"); itemVehicleOverrideYawMethod = AccessTools.Method(typeof(ItemVehicle), "OverrideYaw", new Type[3] { typeof(Vector3), typeof(float), typeof(int) }, (Type[])null); itemVehicleOverridePitchMethod = AccessTools.Method(typeof(ItemVehicle), "OverridePitch", new Type[2] { typeof(float), typeof(float) }, (Type[])null); playerAvatarSpawnRPCMethod = AccessTools.Method(typeof(PlayerAvatar), "SpawnRPC", new Type[3] { typeof(Vector3), typeof(Quaternion), typeof(PhotonMessageInfo) }, (Type[])null); harmony = new Harmony("REPOJP.ArenaRaceMultiplayerSpawnFix"); harmony.PatchAll(); LogInfo("Loaded ArenaRaceMultiplayerSpawnFix v4.0.2"); LogInfo("Config: Enabled=" + GetConfigBool(enabledConfig, defaultValue: false) + ", HorizontalPlayers=" + GetConfigInt(horizontalPlayersConfig, 10) + ", VerticalPlayers=" + GetConfigInt(verticalPlayersConfig, 2) + ", StartBoostEnabled=" + GetConfigBool(startBoostEnabledConfig, defaultValue: false) + ", StartBoostMultiplier=" + GetConfigFloat(startBoostMultiplierConfig, 10f)); if (arenaRacePlayerVehicleMapField == null) { LogWarning("Warning: ArenaRace.playerVehicleMap field was not found. Start boost will use fallback vehicle list if available."); } if (arenaRaceVehiclesField == null) { LogWarning("Warning: ArenaRace.vehicles field was not found. Start boost fallback vehicle list is unavailable."); } if (itemVehicleOverrideYawMethod == null) { LogWarning("Warning: ItemVehicle.OverrideYaw method was not found. Start boost cannot be applied."); } if (playerAvatarSpawnRPCMethod == null) { LogWarning("Warning: PlayerAvatar.SpawnRPC method was not found. Singleplayer compatibility fallback is unavailable."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Awake\n" + ex)); } } private void OnDestroy() { try { if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex) { LogError("Failure: OnDestroy\n" + ex); } } private void BindConfig() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown enabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod.このMODを有効にします"); horizontalPlayersConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Spawn Layout", "HorizontalPlayers", 10, new ConfigDescription("Number of players per horizontal row.横1行に並べる人数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); verticalPlayersConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Spawn Layout", "VerticalPlayers", 2, new ConfigDescription("Number of vertical rows.縦方向の行数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); startBoostEnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Start Boost", "StartBoostEnabled", true, "Apply a temporary level 3 boost after the countdown.321後に一時的なレベル3ブーストを付与します"); startBoostMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Start Boost", "StartBoostMultiplier", 10f, new ConfigDescription("Level 3 boost power multiplier.レベル3ブーストの強さ倍率", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); } private static void ScheduleLayoutApplyFromPlayerSpawn() { if (!CanScheduleLayoutApply(out var reason)) { LogWarning("Skipped layout schedule: " + reason + " | " + BuildContextSummary()); return; } if ((Object)(object)pluginInstance == (Object)null) { LogWarning("Skipped layout schedule: plugin instance is null | " + BuildContextSummary()); return; } lastStartBoostArenaRaceInstanceId = 0; layoutScheduleId++; int scheduleId = layoutScheduleId; LogInfo("PlayerSpawn detected. Scheduling Arena Race spawn layout. ScheduleId=" + scheduleId + " | " + BuildContextSummary()); ((MonoBehaviour)pluginInstance).StartCoroutine(DelayedApplyLayoutCoroutine(scheduleId)); } [IteratorStateMachine(typeof(<DelayedApplyLayoutCoroutine>d__31))] private static IEnumerator DelayedApplyLayoutCoroutine(int scheduleId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedApplyLayoutCoroutine>d__31(0) { scheduleId = scheduleId }; } private static void TryApplyLayout(int scheduleId, int attempt) { if (layoutApplyInProgress) { LogWarning("Skipped layout apply: another layout apply is already running. ScheduleId=" + scheduleId); return; } layoutApplyInProgress = true; try { List<PlayerAvatar> randomizedPlayers = GetRandomizedPlayers(); if (randomizedPlayers.Count == 0) { LogWarning("Skipped layout apply: no valid players found | ScheduleId=" + scheduleId + " | " + BuildContextSummary()); return; } LayoutPlan layoutPlan = BuildLayoutPlan(randomizedPlayers); if (layoutPlan == null || layoutPlan.Positions.Count == 0) { LogWarning("Skipped layout apply: layout plan is empty | ScheduleId=" + scheduleId + " | Players=" + randomizedPlayers.Count); return; } int num = ApplyLayout(randomizedPlayers, layoutPlan); LogInfo("Applied Arena Race spawn layout by SpawnRPC. ScheduleId=" + scheduleId + ", Attempt=" + attempt + ", Players=" + randomizedPlayers.Count + ", Applied=" + num + ", HorizontalPlayers=" + GetConfigInt(horizontalPlayersConfig, 10) + ", VerticalPlayers=" + GetConfigInt(verticalPlayersConfig, 2) + ", Slots=" + layoutPlan.Positions.Count + " | " + BuildContextSummary()); } catch (Exception ex) { LogError("Failure: TryApplyLayout | ScheduleId=" + scheduleId + " | " + BuildContextSummary() + "\n" + ex); } finally { layoutApplyInProgress = false; } } private static bool CanScheduleLayoutApply(out string reason) { if (enabledConfig == null || !enabledConfig.Value) { reason = "mod is disabled"; return false; } if (!SafeIsMasterClientOrSingleplayer()) { reason = "not host or singleplayer"; return false; } if ((Object)(object)LevelGenerator.Instance == (Object)null) { reason = "LevelGenerator.Instance is null"; return false; } if (!SafeCurrentLevelLooksArenaRace() && !SafeArenaRaceInstanceExists()) { reason = "current level is not Arena Race"; return false; } if (SafeLevelGenerated()) { reason = "level is already generated"; return false; } reason = "ready"; return true; } private static bool CanApplyLayoutNow(out string reason) { if (enabledConfig == null || !enabledConfig.Value) { reason = "mod is disabled"; return false; } if (!SafeIsMasterClientOrSingleplayer()) { reason = "not host or singleplayer"; return false; } if (!SafeCurrentLevelLooksArenaRace() && !SafeArenaRaceInstanceExists()) { reason = "current level is not Arena Race"; return false; } if (!SafeArenaRaceInstanceExists()) { reason = "ArenaRace.instance is null. This is not Arena Race, or Arena Race is not ready yet"; return false; } if (!SafeArenaRaceTrackSpawnOriginExists()) { reason = "ArenaRace.trackSpawnOrigin is null. Arena Race is not ready yet"; return false; } int playerCountSafe = GetPlayerCountSafe(); if (playerCountSafe <= 0) { reason = "no players in GameDirector.PlayerList"; return false; } reason = "ready"; return true; } private static List<PlayerAvatar> GetRandomizedPlayers() { List<PlayerAvatar> list = new List<PlayerAvatar>(); if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return list; } foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null) { list.Add(player); } } return ShufflePlayers(list); } private static LayoutPlan BuildLayoutPlan(List<PlayerAvatar> players) { //IL_0026: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) LayoutPlan layoutPlan = new LayoutPlan(); if (players == null || players.Count == 0) { return layoutPlan; } Vector3 val = GetVanillaCenter(players) + Vector3.up * 5f; Vector3 courseForward = GetCourseForward(); Vector3 val2 = Vector3.Cross(Vector3.up, courseForward); Vector3 val3 = ((Vector3)(ref val2)).normalized; if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = Vector3.right; } int num = Mathf.Clamp((horizontalPlayersConfig != null) ? horizontalPlayersConfig.Value : 10, 1, 20); int num2 = Mathf.Clamp((verticalPlayersConfig != null) ? verticalPlayersConfig.Value : 2, 1, 20); int num3 = Mathf.CeilToInt((float)players.Count / (float)Mathf.Max(1, num)); num2 = Mathf.Max(num2, num3); List<Vector3> list = new List<Vector3>(); for (int i = 0; i < num2; i++) { for (int j = 0; j < num; j++) { float num4 = ((float)j - ((float)num - 1f) * 0.5f) * 0.8f; float num5 = 0f - ((float)i * 3f + 10f); Vector3 item = val + val3 * num4 + courseForward * num5; list.Add(item); } } list = ShufflePositions(list); for (int k = 0; k < players.Count && k < list.Count; k++) { layoutPlan.Positions.Add(list[k]); } return layoutPlan; } private static List<Vector3> ShufflePositions(List<Vector3> positions) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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) List<Vector3> list = new List<Vector3>(positions); Random random = new Random(Guid.NewGuid().GetHashCode() ^ Environment.TickCount ^ list.Count); for (int num = list.Count - 1; num > 0; num--) { int index = random.Next(num + 1); Vector3 value = list[num]; list[num] = list[index]; list[index] = value; } return list; } private static int ApplyLayout(List<PlayerAvatar> players, LayoutPlan plan) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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) int num = 0; int num2 = Mathf.Min(players.Count, plan.Positions.Count); for (int i = 0; i < num2; i++) { PlayerAvatar val = players[i]; if ((Object)(object)val == (Object)null) { continue; } try { Vector3 position = plan.Positions[i]; Quaternion rotation = ((Component)val).transform.rotation; if (TryApplySpawnPositionByRpc(val, position, rotation, i)) { num++; } } catch (Exception ex) { LogError("Failure: ApplyLayout player index " + i + "\n" + ex); } } return num; } private static bool TryApplySpawnPositionByRpc(PlayerAvatar player, Vector3 position, Quaternion rotation, int index) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { LogWarning("Skipped SpawnRPC apply: player is null. Index=" + index); return false; } try { if ((Object)(object)GameManager.instance != (Object)null && GameManager.instance.gameMode == 0) { if (playerAvatarSpawnRPCMethod == null) { LogWarning("Skipped SpawnRPC apply: SpawnRPC method was not found. Index=" + index + ", Player=" + GetPlayerDebugName(player)); return false; } playerAvatarSpawnRPCMethod.Invoke(player, new object[3] { position, rotation, (object)default(PhotonMessageInfo) }); return true; } if ((Object)(object)player.photonView == (Object)null) { player.photonView = ((Component)player).GetComponent<PhotonView>(); } if ((Object)(object)player.photonView == (Object)null) { LogWarning("Skipped SpawnRPC apply: PhotonView is null. Index=" + index + ", Player=" + GetPlayerDebugName(player)); return false; } player.photonView.RPC("SpawnRPC", (RpcTarget)0, new object[2] { position, rotation }); return true; } catch (Exception ex) { LogError("Failure: TryApplySpawnPositionByRpc | Index=" + index + ", Player=" + GetPlayerDebugName(player) + "\n" + ex); return false; } } private static string GetPlayerDebugName(PlayerAvatar player) { try { if ((Object)(object)player == (Object)null) { return "null"; } if (!string.IsNullOrEmpty(((Object)player).name)) { return ((Object)player).name; } return "Unknown"; } catch { return "Unknown"; } } private static Vector3 GetVanillaCenter(List<PlayerAvatar> players) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; int num = 0; foreach (PlayerAvatar player in players) { if (!((Object)(object)player == (Object)null)) { val += ((Component)player).transform.position; num++; } } if (num == 0) { return Vector3.zero; } return val / (float)num; } private static Vector3 GetCourseForward() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = Vector3.forward; try { if ((Object)(object)ArenaRace.instance != (Object)null && (Object)(object)ArenaRace.instance.trackSpawnOrigin != (Object)null) { forward = ArenaRace.instance.trackSpawnOrigin.forward; } } catch { } forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f) { forward = Vector3.forward; } return ((Vector3)(ref forward)).normalized; } private static List<PlayerAvatar> ShufflePlayers(List<PlayerAvatar> players) { List<PlayerAvatar> list = new List<PlayerAvatar>(players); Random random = new Random(Guid.NewGuid().GetHashCode() ^ Environment.TickCount); for (int num = list.Count - 1; num > 0; num--) { int index = random.Next(num + 1); PlayerAvatar value = list[num]; list[num] = list[index]; list[index] = value; } return list; } private static void ApplyStartBoostOnce(ArenaRace arenaRace) { if ((Object)(object)arenaRace == (Object)null || enabledConfig == null || !enabledConfig.Value || startBoostEnabledConfig == null || !startBoostEnabledConfig.Value || !SafeIsMasterClientOrSingleplayer()) { return; } if ((Object)(object)arenaRace == (Object)null && !SafeRunIsArena()) { LogWarning("Skipped start boost: Arena Race was not detected | " + BuildContextSummary()); return; } int instanceID = ((Object)arenaRace).GetInstanceID(); if (lastStartBoostArenaRaceInstanceId == instanceID) { return; } lastStartBoostArenaRaceInstanceId = instanceID; List<ItemVehicle> arenaRaceVehicles = GetArenaRaceVehicles(arenaRace); if (arenaRaceVehicles.Count == 0) { LogWarning("Skipped start boost: no Arena Race vehicles found | " + BuildContextSummary()); return; } int num = 0; foreach (ItemVehicle item in arenaRaceVehicles) { if (ApplyStartBoostToVehicle(arenaRace, item)) { num++; } } LogInfo("Applied start boost. Vehicles=" + arenaRaceVehicles.Count + ", Applied=" + num + ", Multiplier=" + GetConfigFloat(startBoostMultiplierConfig, 10f)); } private static List<ItemVehicle> GetArenaRaceVehicles(ArenaRace arenaRace) { List<ItemVehicle> list = new List<ItemVehicle>(); if ((Object)(object)arenaRace == (Object)null) { return list; } try { if (arenaRacePlayerVehicleMapField != null) { object value = arenaRacePlayerVehicleMapField.GetValue(arenaRace); if (value is Dictionary<PlayerAvatar, ItemVehicle> dictionary) { foreach (KeyValuePair<PlayerAvatar, ItemVehicle> item in dictionary) { if ((Object)(object)item.Value != (Object)null && !list.Contains(item.Value)) { list.Add(item.Value); } } } } } catch { } try { if (list.Count == 0 && arenaRaceVehiclesField != null) { object value2 = arenaRaceVehiclesField.GetValue(arenaRace); if (value2 is List<ItemVehicle> list2) { foreach (ItemVehicle item2 in list2) { if ((Object)(object)item2 != (Object)null && !list.Contains(item2)) { list.Add(item2); } } } } } catch { } return list; } private static bool ApplyStartBoostToVehicle(ArenaRace arenaRace, ItemVehicle vehicle) { //IL_008b: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)arenaRace == (Object)null || (Object)(object)vehicle == (Object)null) { return false; } if (itemVehicleOverrideYawMethod == null) { return false; } float driftBoostLevel3ForwardBoost = vehicle.driftBoostLevel3ForwardBoost; float driftBoostLevel3SpeedBoostMultiplier = vehicle.driftBoostLevel3SpeedBoostMultiplier; try { float num = ((startBoostMultiplierConfig != null) ? startBoostMultiplierConfig.Value : 10f); float num2 = Mathf.Clamp(num, 0f, 100f); vehicle.driftBoostLevel3ForwardBoost = driftBoostLevel3ForwardBoost * num2; vehicle.driftBoostLevel3SpeedBoostMultiplier = driftBoostLevel3SpeedBoostMultiplier * num2; Vector3 startBoostForward = GetStartBoostForward(arenaRace, vehicle); float num3 = Mathf.Asin(Mathf.Clamp(startBoostForward.y, -1f, 1f)) * 57.29578f; Vector3 val = startBoostForward; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)vehicle).transform.forward; val.y = 0f; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } ((Vector3)(ref val)).Normalize(); itemVehicleOverrideYawMethod.Invoke(vehicle, new object[3] { val, 0.25f, 3 }); if (itemVehicleOverridePitchMethod != null) { itemVehicleOverridePitchMethod.Invoke(vehicle, new object[2] { num3, 1f }); } return true; } catch (Exception ex) { LogError("Failure: ApplyStartBoostToVehicle\n" + ex); return false; } finally { vehicle.driftBoostLevel3ForwardBoost = driftBoostLevel3ForwardBoost; vehicle.driftBoostLevel3SpeedBoostMultiplier = driftBoostLevel3SpeedBoostMultiplier; } } private static Vector3 GetStartBoostForward(ArenaRace arenaRace, ItemVehicle vehicle) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_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) try { if ((Object)(object)arenaRace != (Object)null && (Object)(object)arenaRace.trackSpawnOrigin != (Object)null) { return arenaRace.trackSpawnOrigin.forward; } if ((Object)(object)vehicle != (Object)null) { return ((Component)vehicle).transform.forward; } } catch { } return Vector3.forward; } private static bool SafeIsMasterClientOrSingleplayer() { try { return SemiFunc.IsMasterClientOrSingleplayer(); } catch { return false; } } private static bool SafeCurrentLevelLooksArenaRace() { try { if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)RunManager.instance.levelCurrent == (Object)null) { return false; } string name = ((Object)RunManager.instance.levelCurrent).name; if (string.IsNullOrEmpty(name)) { return false; } return name.IndexOf("Arena Race", StringComparison.OrdinalIgnoreCase) >= 0; } catch { return false; } } private static string SafeCurrentLevelName() { try { if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)RunManager.instance.levelCurrent == (Object)null) { return "null"; } return ((Object)RunManager.instance.levelCurrent).name ?? "null"; } catch { return "Unknown"; } } private static bool SafeArenaRaceInstanceExists() { try { return (Object)(object)ArenaRace.instance != (Object)null; } catch { return false; } } private static bool SafeArenaRaceTrackSpawnOriginExists() { try { return (Object)(object)ArenaRace.instance != (Object)null && (Object)(object)ArenaRace.instance.trackSpawnOrigin != (Object)null; } catch { return false; } } private static bool SafeRunIsArena() { try { return SemiFunc.RunIsArena(); } catch { return false; } } private static bool SafeLevelGenerated() { try { return (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated; } catch { return false; } } private static string BuildContextSummary() { bool configBool = GetConfigBool(enabledConfig, defaultValue: false); bool flag = SafeIsMasterClientOrSingleplayer(); bool flag2 = (Object)(object)LevelGenerator.Instance != (Object)null; bool flag3 = SafeLevelGenerated(); string text = SafeCurrentLevelName(); bool flag4 = SafeCurrentLevelLooksArenaRace(); bool flag5 = SafeArenaRaceInstanceExists(); bool flag6 = SafeArenaRaceTrackSpawnOriginExists(); bool flag7 = SafeRunIsArena(); int playerCountSafe = GetPlayerCountSafe(); int spawnPointCountSafe = GetSpawnPointCountSafe(); bool flag8 = SafeTruckSafetySpawnPointExists(); return "Enabled=" + configBool + ", HostOrSingleplayer=" + flag + ", LevelGenerator=" + flag2 + ", LevelGenerated=" + flag3 + ", CurrentLevel=" + text + ", CurrentLevelIsArenaRace=" + flag4 + ", ArenaRaceInstance=" + flag5 + ", ArenaRaceTrackSpawnOrigin=" + flag6 + ", RunIsArena=" + flag7 + ", PlayerCount=" + playerCountSafe + ", SpawnPointCount=" + spawnPointCountSafe + ", TruckSafetySpawnPoint=" + flag8; } private static int GetPlayerCountSafe() { try { if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return 0; } return GameDirector.instance.PlayerList.Count; } catch { return -1; } } private static int GetSpawnPointCountSafe() { try { SpawnPoint[] array = Object.FindObjectsOfType<SpawnPoint>(); return (array != null) ? array.Length : 0; } catch { return -1; } } private static bool SafeTruckSafetySpawnPointExists() { try { return (Object)(object)TruckSafetySpawnPoint.instance != (Object)null; } catch { return false; } } private static bool GetConfigBool(ConfigEntry<bool> config, bool defaultValue) { try { return config?.Value ?? defaultValue; } catch { return defaultValue; } } private static int GetConfigInt(ConfigEntry<int> config, int defaultValue) { try { return config?.Value ?? defaultValue; } catch { return defaultValue; } } private static float GetConfigFloat(ConfigEntry<float> config, float defaultValue) { try { return config?.Value ?? defaultValue; } catch { return defaultValue; } } private static void LogInfo(string message) { if (logSource != null) { logSource.LogInfo((object)message); } } private static void LogWarning(string message) { if (logSource != null) { logSource.LogWarning((object)message); } } private static void LogError(string message) { if (logSource != null) { logSource.LogError((object)message); } } } }