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 10 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) { } } }