using System; 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 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", "1.5.0")] public class ArenaRaceMultiplayerSpawnFixPlugin : BaseUnityPlugin { private sealed class LayoutPlan { public readonly List Positions = new List(); } [HarmonyPatch(typeof(LevelGenerator), "PlayerSpawn")] private static class LevelGeneratorPlayerSpawnPatch { private static void Postfix() { try { if (!ShouldApplyLayout()) { return; } lastStartBoostArenaRaceInstanceId = 0; List randomizedPlayers = GetRandomizedPlayers(); if (randomizedPlayers.Count != 0) { LayoutPlan layoutPlan = BuildLayoutPlan(randomizedPlayers); if (layoutPlan != null && layoutPlan.Positions.Count != 0) { ApplyLayout(randomizedPlayers, layoutPlan); } } } 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); } } } public const string PluginGuid = "REPOJP.ArenaRaceMultiplayerSpawnFix"; public const string PluginName = "ArenaRaceMultiplayerSpawnFix"; public const string PluginVersion = "1.5.0"; 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 ConfigEntry enabledConfig; private static ConfigEntry horizontalPlayersConfig; private static ConfigEntry verticalPlayersConfig; private static ConfigEntry startBoostEnabledConfig; private static ConfigEntry startBoostMultiplierConfig; private static FieldInfo arenaRacePlayerVehicleMapField; private static FieldInfo arenaRaceVehiclesField; private static MethodInfo itemVehicleOverrideYawMethod; private static MethodInfo itemVehicleOverridePitchMethod; private static int lastStartBoostArenaRaceInstanceId; private void Awake() { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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); 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); harmony = new Harmony("REPOJP.ArenaRaceMultiplayerSpawnFix"); harmony.PatchAll(); } 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("General", "Enabled", true, "Enable this mod.このMODを有効にします"); horizontalPlayersConfig = ((BaseUnityPlugin)this).Config.Bind("Spawn Layout", "HorizontalPlayers", 10, new ConfigDescription("Number of players per horizontal row.横1行に並べる人数", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20), Array.Empty())); verticalPlayersConfig = ((BaseUnityPlugin)this).Config.Bind("Spawn Layout", "VerticalPlayers", 2, new ConfigDescription("Number of vertical rows.縦方向の行数", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20), Array.Empty())); startBoostEnabledConfig = ((BaseUnityPlugin)this).Config.Bind("Start Boost", "StartBoostEnabled", true, "Apply a temporary level 3 boost after the countdown.321後に一時的なレベル3ブーストを付与します"); startBoostMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind("Start Boost", "StartBoostMultiplier", 10f, new ConfigDescription("Level 3 boost power multiplier.レベル3ブーストの強さ倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); } private static bool ShouldApplyLayout() { if (enabledConfig == null || !enabledConfig.Value) { return false; } if (!SafeIsMasterClientOrSingleplayer()) { return false; } if ((Object)(object)LevelGenerator.Instance == (Object)null || SafeLevelGenerated()) { return false; } if ((Object)(object)ArenaRace.instance == (Object)null) { return false; } if (!SafeRunIsArena()) { return false; } return true; } private static List GetRandomizedPlayers() { List list = new List(); 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 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 list = new List(); 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 ShufflePositions(List 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 list = new List(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 void ApplyLayout(List players, LayoutPlan plan) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Min(players.Count, plan.Positions.Count); for (int i = 0; i < num; i++) { PlayerAvatar val = players[i]; if (!((Object)(object)val == (Object)null)) { Vector3 val2 = plan.Positions[i]; Quaternion rotation = ((Component)val).transform.rotation; val.Spawn(val2, rotation); } } } private static Vector3 GetVanillaCenter(List 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 ShufflePlayers(List players) { List list = new List(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() || !SafeRunIsArena()) { return; } int instanceID = ((Object)arenaRace).GetInstanceID(); if (lastStartBoostArenaRaceInstanceId == instanceID) { return; } lastStartBoostArenaRaceInstanceId = instanceID; List arenaRaceVehicles = GetArenaRaceVehicles(arenaRace); foreach (ItemVehicle item in arenaRaceVehicles) { ApplyStartBoostToVehicle(arenaRace, item); } } private static List GetArenaRaceVehicles(ArenaRace arenaRace) { List list = new List(); if ((Object)(object)arenaRace == (Object)null) { return list; } try { if (arenaRacePlayerVehicleMapField != null) { object value = arenaRacePlayerVehicleMapField.GetValue(arenaRace); if (value is Dictionary dictionary) { foreach (KeyValuePair 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 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 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 void LogError(string message) { if (logSource != null) { logSource.LogError((object)message); } } } }