Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of Rain Better Skateboards IL2CPP v1.0.0
RainsBetterSkateboardsIL2CPP.dll
Decompiled 2 months agousing System; 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 Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne.Skating; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using RainsBetterSkateboard; using RainsBetterSkateboardsIL2CPP.Logging; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(BetterSkateboardTweaks_IL2CPP), "RainsBetterSkateboardsIL2CPP", "1.0.0", "RainingDeath", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("RainsBetterSkateboardsIL2CPP")] [assembly: AssemblyConfiguration("DebugMelon")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RainsBetterSkateboardsIL2CPP")] [assembly: AssemblyTitle("RainsBetterSkateboardsIL2CPP")] [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; } } } [Serializable] public class SkateConfigRoot { public SkateboardBoard[] Boards = Array.Empty<SkateboardBoard>(); } [Serializable] public class SkateboardBoard { public string Name; public float TopSpeed_Kmh; public float ReverseTopSpeed_Kmh; public float TurnForce; public float TurnChangeRate; public float TurnReturnToRestRate; public float TurnSpeedBoost; public float Gravity; public float BrakeForce; public float RotationClampForce; public float HoverForce; public float HoverHeight; public float HoverRayLength; public float Hover_P; public float Hover_I; public float Hover_D; public bool SlowOnTerrain; public bool FrictionEnabled; public float LongitudinalFrictionMultiplier; public float LateralFrictionForceMultiplier; public float JumpForce; public float JumpDuration_Min; public float JumpDuration_Max; public float JumpForwardBoost; public float PushForceMultiplier; public float PushForceDuration; public float PushDelay; public bool AirMovementEnabled; public float AirMovementForce; public float AirMovementJumpReductionDuration; public static SkateboardBoard FromPrefab(string name, Skateboard s) { SkateboardBoard skateboardBoard = new SkateboardBoard(); skateboardBoard.Name = name; skateboardBoard.TopSpeed_Kmh = s.TopSpeed_Kmh; skateboardBoard.ReverseTopSpeed_Kmh = s.ReverseTopSpeed_Kmh; skateboardBoard.TurnForce = s.TurnForce; skateboardBoard.TurnChangeRate = s.TurnChangeRate; skateboardBoard.TurnReturnToRestRate = s.TurnReturnToRestRate; skateboardBoard.TurnSpeedBoost = s.TurnSpeedBoost; skateboardBoard.Gravity = s.Gravity; skateboardBoard.BrakeForce = s.BrakeForce; skateboardBoard.RotationClampForce = s.RotationClampForce; skateboardBoard.HoverForce = s.HoverForce; skateboardBoard.HoverHeight = s.HoverHeight; skateboardBoard.HoverRayLength = s.HoverRayLength; skateboardBoard.Hover_P = s.Hover_P; skateboardBoard.Hover_I = s.Hover_I; skateboardBoard.Hover_D = s.Hover_D; skateboardBoard.SlowOnTerrain = s.SlowOnTerrain; skateboardBoard.FrictionEnabled = s.FrictionEnabled; skateboardBoard.LongitudinalFrictionMultiplier = s.LongitudinalFrictionMultiplier; skateboardBoard.LateralFrictionForceMultiplier = s.LateralFrictionForceMultiplier; skateboardBoard.JumpForce = s.JumpForce; skateboardBoard.JumpDuration_Min = s.JumpDuration_Min; skateboardBoard.JumpDuration_Max = s.JumpDuration_Max; skateboardBoard.JumpForwardBoost = s.JumpForwardBoost; skateboardBoard.PushForceMultiplier = s.PushForceMultiplier; skateboardBoard.PushForceDuration = s.PushForceDuration; skateboardBoard.PushDelay = s.PushDelay; skateboardBoard.AirMovementEnabled = s.AirMovementEnabled; skateboardBoard.AirMovementForce = s.AirMovementForce; skateboardBoard.AirMovementJumpReductionDuration = s.AirMovementJumpReductionDuration; return skateboardBoard; } } namespace RainsBetterSkateboardsIL2CPP { public class Core : MelonMod { public override void OnInitializeMelon() { Log.LogInfo("Initializing RainsBetterSkateboardsIL2CPP..."); } } } namespace RainsBetterSkateboardsIL2CPP.Logging { public static class Log { public static void LogInfo(string message) { Melon<Core>.Logger.Msg(message); } public static void LogWarning(string message) { Melon<Core>.Logger.Warning(message); } public static void LogError(string message) { Melon<Core>.Logger.Error(message); } public static void LogFatal(string message) { Melon<Core>.Logger.BigError(message); } } } namespace RainsBetterSkateboard { public sealed class BetterSkateboardTweaks_IL2CPP : MelonMod { private static readonly string ConfigPath = Path.Combine(MelonEnvironment.ModsDirectory, "BetterSkateboardConfig.json"); private static SkateConfigRoot _config = new SkateConfigRoot(); private static bool _hadConfigAtStart; public override void OnInitializeMelon() { _config = LoadConfig(out _hadConfigAtStart) ?? new SkateConfigRoot(); if (_hadConfigAtStart) { MelonLogger.Msg($"[BetterSkateboard] Loaded config for {_config.Boards.Length} boards at startup."); } else { MelonLogger.Msg("[BetterSkateboard] No valid config at startup; will write defaults after prefabs are found in Main."); } } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (!sceneName.Equals("Main", StringComparison.OrdinalIgnoreCase)) { return; } Dictionary<string, Skateboard> dictionary = FindSkateboardPrefabsByName(); if (dictionary.Count == 0) { MelonLogger.Warning("[BetterSkateboard] Could not isolate any skateboard prefabs."); return; } List<string> list = new List<string>(dictionary.Keys); list.Sort(StringComparer.Ordinal); MelonLogger.Msg("[BetterSkateboard] Prefabs discovered: " + string.Join(", ", list.ToArray())); if (!_hadConfigAtStart) { List<SkateboardBoard> list2 = new List<SkateboardBoard>(dictionary.Count); foreach (KeyValuePair<string, Skateboard> item in dictionary) { list2.Add(SkateboardBoard.FromPrefab(item.Key, item.Value)); } _config.Boards = list2.ToArray(); string json = JsonConvert.SerializeObject((object)_config, (Formatting)1); SafeWrite(ConfigPath, json); _hadConfigAtStart = true; MelonLogger.Msg("[BetterSkateboard] Wrote defaults → " + ConfigPath); return; } int num = 0; int num2 = 0; SkateboardBoard[] boards = _config.Boards; if (boards != null) { foreach (SkateboardBoard skateboardBoard in boards) { if (skateboardBoard == null || string.IsNullOrEmpty(skateboardBoard.Name)) { num2++; continue; } if (!dictionary.TryGetValue(skateboardBoard.Name, out var value) || (Object)(object)value == (Object)null) { num2++; MelonLogger.Warning("[BetterSkateboard] Prefab not found for '" + skateboardBoard.Name + "' (exact match)."); continue; } value.TopSpeed_Kmh = skateboardBoard.TopSpeed_Kmh; value.ReverseTopSpeed_Kmh = skateboardBoard.ReverseTopSpeed_Kmh; value.TurnForce = skateboardBoard.TurnForce; value.TurnChangeRate = skateboardBoard.TurnChangeRate; value.TurnReturnToRestRate = skateboardBoard.TurnReturnToRestRate; value.TurnSpeedBoost = skateboardBoard.TurnSpeedBoost; value.Gravity = skateboardBoard.Gravity; value.BrakeForce = skateboardBoard.BrakeForce; value.RotationClampForce = skateboardBoard.RotationClampForce; value.HoverForce = skateboardBoard.HoverForce; value.HoverHeight = skateboardBoard.HoverHeight; value.HoverRayLength = skateboardBoard.HoverRayLength; value.Hover_P = skateboardBoard.Hover_P; value.Hover_I = skateboardBoard.Hover_I; value.Hover_D = skateboardBoard.Hover_D; value.SlowOnTerrain = skateboardBoard.SlowOnTerrain; value.FrictionEnabled = skateboardBoard.FrictionEnabled; value.LongitudinalFrictionMultiplier = skateboardBoard.LongitudinalFrictionMultiplier; value.LateralFrictionForceMultiplier = skateboardBoard.LateralFrictionForceMultiplier; value.JumpForce = skateboardBoard.JumpForce; value.JumpDuration_Min = skateboardBoard.JumpDuration_Min; value.JumpDuration_Max = skateboardBoard.JumpDuration_Max; value.JumpForwardBoost = skateboardBoard.JumpForwardBoost; value.PushForceMultiplier = skateboardBoard.PushForceMultiplier; value.PushForceDuration = skateboardBoard.PushForceDuration; value.PushDelay = skateboardBoard.PushDelay; value.AirMovementEnabled = skateboardBoard.AirMovementEnabled; value.AirMovementForce = skateboardBoard.AirMovementForce; value.AirMovementJumpReductionDuration = skateboardBoard.AirMovementJumpReductionDuration; num++; MelonLogger.Msg($"[BetterSkateboard] Patched '{skateboardBoard.Name}' (HoverHeight={value.HoverHeight}, HoverForce={value.HoverForce}, TopSpeed_Kmh={value.TopSpeed_Kmh})"); } } MelonLogger.Msg($"[BetterSkateboard] Applied {num} prefab(s) from config. Missing: {num2}."); } private static Dictionary<string, Skateboard> FindSkateboardPrefabsByName() { //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, Skateboard> dictionary = new Dictionary<string, Skateboard>(8); Il2CppReferenceArray<Object> val = Resources.FindObjectsOfTypeAll(Il2CppType.Of<Skateboard>()); if (val == null || ((Il2CppArrayBase<Object>)(object)val).Length == 0) { return dictionary; } for (int i = 0; i < ((Il2CppArrayBase<Object>)(object)val).Length; i++) { Object val2 = ((Il2CppArrayBase<Object>)(object)val)[i]; Skateboard val3 = ((Il2CppObjectBase)val2).TryCast<Skateboard>(); if (!((Object)(object)val3 == (Object)null)) { object obj = ((Object)val3).name; if (obj == null) { GameObject gameObject = ((Component)val3).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null) ?? string.Empty; } string text = (string)obj; if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - "(Clone)".Length).TrimEnd(); } if (!string.IsNullOrEmpty(text) && !dictionary.ContainsKey(text)) { dictionary.Add(text, val3); } } } if (dictionary.Count == 0) { List<string> list = new List<string>(); for (int j = 0; j < ((Il2CppArrayBase<Object>)(object)val).Length; j++) { Object obj2 = ((Il2CppArrayBase<Object>)(object)val)[j]; Skateboard val4 = (Skateboard)(object)((obj2 is Skateboard) ? obj2 : null); if (!((Object)(object)val4 == (Object)null)) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(19, 3); defaultInterpolatedStringHandler.AppendFormatted(((Object)val4).name); defaultInterpolatedStringHandler.AppendLiteral(" (GO:"); GameObject gameObject2 = ((Component)val4).gameObject; defaultInterpolatedStringHandler.AppendFormatted((gameObject2 != null) ? ((Object)gameObject2).name : null); defaultInterpolatedStringHandler.AppendLiteral(", sceneValid:"); GameObject gameObject3 = ((Component)val4).gameObject; bool? value; if (gameObject3 == null) { value = null; } else { Scene scene = gameObject3.scene; value = ((Scene)(ref scene)).IsValid(); } defaultInterpolatedStringHandler.AppendFormatted(value); defaultInterpolatedStringHandler.AppendLiteral(")"); list.Add(defaultInterpolatedStringHandler.ToStringAndClear()); } } MelonLogger.Warning("[BetterSkateboard] Saw Skateboards: " + string.Join(", ", list)); } return dictionary; } private static SkateConfigRoot LoadConfig(out bool had) { had = false; try { string directoryName = Path.GetDirectoryName(ConfigPath); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } if (!File.Exists(ConfigPath)) { return null; } string text = File.ReadAllText(ConfigPath); SkateConfigRoot skateConfigRoot = JsonConvert.DeserializeObject<SkateConfigRoot>(text); if (skateConfigRoot?.Boards != null && skateConfigRoot.Boards.Length != 0) { had = true; return skateConfigRoot; } if (text.TrimStart().StartsWith("[")) { string text2 = "{\"Boards\":" + text + "}"; skateConfigRoot = JsonConvert.DeserializeObject<SkateConfigRoot>(text2); if (skateConfigRoot?.Boards != null && skateConfigRoot.Boards.Length != 0) { had = true; return skateConfigRoot; } } SkateboardBoard skateboardBoard = JsonConvert.DeserializeObject<SkateboardBoard>(text); if (skateboardBoard != null && !string.IsNullOrEmpty(skateboardBoard.Name)) { had = true; SkateConfigRoot skateConfigRoot2 = new SkateConfigRoot(); skateConfigRoot2.Boards = new SkateboardBoard[1] { skateboardBoard }; return skateConfigRoot2; } had = true; return new SkateConfigRoot { Boards = Array.Empty<SkateboardBoard>() }; } catch { return null; } } private static void SafeWrite(string path, string json) { try { string directoryName = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } if (File.Exists(path)) { File.Copy(path, path + ".bak", overwrite: true); } string text = path + ".tmp"; File.WriteAllText(text, json); if (File.Exists(path)) { File.Delete(path); } File.Move(text, path); } catch (Exception ex) { MelonLogger.Warning("[BetterSkateboard] SafeWrite failed: " + ex.Message); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }