using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppRUMBLE.Managers;
using Il2CppRUMBLE.Players;
using Il2CppRUMBLE.Utilities;
using MelonLoader;
using Microsoft.CodeAnalysis;
using RumbleModUI;
using RumbleModdingAPI;
using SketchbookPlus;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(main), "SketchbookPlus", "1.0.1", "UlvakSkillz", null)]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: MelonColor(255, 195, 0, 255)]
[assembly: MelonAuthorColor(255, 195, 0, 255)]
[assembly: VerifyLoaderVersion(0, 6, 6, true)]
[assembly: AssemblyDescription("")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3b03f008-9dbb-4382-a110-b59ee8b632ca")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SketchbookPlus")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SketchbookPlus")]
[assembly: AssemblyTitle("SketchbookPlus")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace SketchbookPlus
{
public static class BuildInfo
{
public const string ModName = "SketchbookPlus";
public const string ModVersion = "1.0.1";
public const string Author = "UlvakSkillz";
}
public class main : MelonMod
{
public static Mod SketchbookPlus = new Mod();
private string currentScene = "Loader";
private bool randomOutfit = false;
private Random random = new Random();
private List<string> acceptedFiles = new List<string>();
private List<string> failedFiles = new List<string>();
private List<string> pendingFiles = new List<string>();
private List<string> acceptedFilesTexts = new List<string>();
private List<string> pendingFilesTexts = new List<string>();
private int lastOutfit = -1;
private bool debug = false;
private void Log(string msg)
{
MelonLogger.Msg(msg);
}
private void debugLog(string msg)
{
if (debug)
{
MelonLogger.Msg("-" + msg);
}
}
public override void OnLateInitializeMelon()
{
//IL_0060: 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_0072: Expected O, but got Unknown
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected O, but got Unknown
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Expected O, but got Unknown
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Expected O, but got Unknown
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Expected O, but got Unknown
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Expected O, but got Unknown
if (!Directory.Exists("UserData\\SketchbookPlus"))
{
Directory.CreateDirectory("UserData\\SketchbookPlus");
}
SketchbookPlus.ModName = "SketchbookPlus";
SketchbookPlus.ModVersion = "1.0.1";
SketchbookPlus.SetFolder("SketchbookPlus");
SketchbookPlus.AddToList("Save Outfit", false, 1, "Set to True and Save to Store the Equipped Outfit", new Tags
{
DoNotSave = true
});
SketchbookPlus.AddToList("Saved Outfit Name", "DefaultName", "File Name To Save Under", new Tags());
SketchbookPlus.AddToList("Load Outfit", false, 1, "(Not Usable in Pit or Ring) Set to True and Save to Load the Selected Outfit", new Tags());
SketchbookPlus.AddToList("Outfit Name to Load", "DefaultName", "Outfit to Load", new Tags());
SketchbookPlus.AddToList("Random Saved Outfit", false, 0, "Selects a Random Outfit from Saved Outfit Files", new Tags());
SketchbookPlus.AddToList("Update Files Texts", false, 0, "Set to True to refresh the Mod's Data from Files", new Tags
{
DoNotSave = true
});
SketchbookPlus.GetFromFile();
UI.instance.UI_Initialized += UIInit;
SketchbookPlus.ModSaved += Save;
Calls.onMapInitialized += mapInit;
pendingFiles.Clear();
acceptedFiles.Clear();
failedFiles.Clear();
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
currentScene = sceneName;
debugLog("Loading Scene: " + currentScene);
}
private void UIInit()
{
UI.instance.AddMod(SketchbookPlus);
}
private void Save()
{
debugLog("Main Method Running");
bool flag = (bool)SketchbookPlus.Settings[0].SavedValue;
string text = (string)SketchbookPlus.Settings[1].SavedValue;
bool flag2 = (bool)SketchbookPlus.Settings[2].SavedValue;
string text2 = (string)SketchbookPlus.Settings[3].SavedValue;
randomOutfit = (bool)SketchbookPlus.Settings[4].SavedValue;
SketchbookPlus.Settings[0].Value = false;
SketchbookPlus.Settings[0].SavedValue = false;
if ((bool)SketchbookPlus.Settings[5].SavedValue)
{
debugLog("Clearing Known Files");
SketchbookPlus.Settings[5].Value = false;
SketchbookPlus.Settings[5].SavedValue = false;
pendingFiles.Clear();
acceptedFiles.Clear();
failedFiles.Clear();
}
debugLog("Rechecking Files");
recheckFiles();
debugLog("Done Rechecking Files");
if (!text.ToLower().EndsWith(".txt"))
{
text += ".txt";
}
if (!text2.ToLower().EndsWith(".txt"))
{
text2 += ".txt";
}
if (flag)
{
debugLog("Saving Outfit: UserData\\SketchbookPlus\\" + text);
string outfitString = getOutfitString(Singleton<PlayerManager>.instance.localPlayer.Data.visualData);
debugLog("File Text: " + outfitString);
saveFile(outfitString, "UserData\\SketchbookPlus\\" + text);
}
else
{
if (!(currentScene == "Gym"))
{
return;
}
if (randomOutfit && acceptedFiles.Count > 0)
{
int num = random.Next(0, acceptedFiles.Count);
while (num == lastOutfit && acceptedFiles.Count > 1)
{
num = random.Next(0, acceptedFiles.Count);
}
debugLog("Loading Random: " + acceptedFiles[num]);
loadOutfit(acceptedFiles[num]);
lastOutfit = num;
}
else if (flag2)
{
debugLog("Loading Selected: " + text2);
loadOutfit("UserData\\SketchbookPlus\\" + text2);
}
}
}
private void recheckFiles()
{
string[] files = Directory.GetFiles("UserData\\SketchbookPlus");
string[] array = files;
foreach (string text in array)
{
if (!(text == "UserData\\SketchbookPlus\\Settings.txt") && !failedFiles.Contains(text) && !acceptedFiles.Contains(text))
{
debugLog("Pending File: " + text);
pendingFiles.Add(text);
}
}
loadFileTexts();
while (pendingFiles.Count > 0)
{
if (!CheckFileValidity(pendingFiles[0]))
{
Log("Removing Bad File: " + pendingFiles[0]);
Log("Removing Bad File's Text: " + pendingFilesTexts[0]);
failedFiles.Add(pendingFiles[0]);
pendingFiles.Remove(pendingFiles[0]);
pendingFilesTexts.RemoveAt(0);
}
else
{
debugLog("Accepting file: " + pendingFiles[0]);
acceptedFiles.Add(pendingFiles[0]);
acceptedFilesTexts.Add(pendingFilesTexts[0]);
pendingFiles.Remove(pendingFiles[0]);
pendingFilesTexts.RemoveAt(0);
}
}
}
private void saveFile(string textToSave, string file)
{
if (!File.Exists(file))
{
acceptedFiles.Add(file);
}
FileStream fileStream = File.Create(file);
byte[] bytes = Encoding.UTF8.GetBytes(textToSave);
fileStream.Write(bytes);
fileStream.Close();
fileStream.Dispose();
Log("Saving " + file + " Complete");
}
private string getOutfitString(PlayerVisualData pvd)
{
string text = "";
for (int i = 0; i < ((Il2CppArrayBase<short>)(object)pvd.ColorationIndexes).Count; i++)
{
text = text + ((Il2CppArrayBase<short>)(object)pvd.ColorationIndexes)[i] + ",";
}
for (int j = 0; j < ((Il2CppArrayBase<short>)(object)pvd.CustomizationPartIndexes).Count; j++)
{
text = text + ((Il2CppArrayBase<short>)(object)pvd.CustomizationPartIndexes)[j] + ",";
}
for (int k = 0; k < ((Il2CppArrayBase<short>)(object)pvd.OtherCustomizationIndexes).Count; k++)
{
text = text + ((Il2CppArrayBase<short>)(object)pvd.OtherCustomizationIndexes)[k] + ",";
}
for (int l = 0; l < ((Il2CppArrayBase<short>)(object)pvd.TextureCustomizationIndexes).Count; l++)
{
text = text + ((Il2CppArrayBase<short>)(object)pvd.TextureCustomizationIndexes)[l] + ",";
}
for (int m = 0; m < ((Il2CppArrayBase<short>)(object)pvd.TextureOpacityIndexes).Count; m++)
{
text = text + ((Il2CppArrayBase<short>)(object)pvd.TextureOpacityIndexes)[m] + ",";
}
for (int n = 0; n < ((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes).Count; n++)
{
text += ((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes)[n];
if (n != ((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes).Count - 1)
{
text += ",";
}
}
return text;
}
private void loadOutfit(string fileName)
{
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Expected O, but got Unknown
if (acceptedFiles.IndexOf(fileName) == -1)
{
MelonLogger.Error("Not An Accepted File: " + fileName);
return;
}
Log("Text: " + acceptedFilesTexts[acceptedFiles.IndexOf(fileName)]);
string[] data = acceptedFilesTexts[acceptedFiles.IndexOf(fileName)].Split(',');
PlayerVisualData visualData = Singleton<PlayerManager>.instance.localPlayer.Data.VisualData;
PlayerVisualData val = new PlayerVisualData(visualData);
setPVD(val, data);
if (checkItems(val.ToPlayfabDataString()))
{
debugLog("Setting PVD Now");
setPVD(visualData, val);
Log("Loaded Outfit for Next Scene: " + fileName);
}
}
private bool CheckFileValidity(string fileName)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Expected O, but got Unknown
string[] data = pendingFilesTexts[pendingFiles.IndexOf(fileName)].Split(',');
PlayerVisualData val = new PlayerVisualData(Singleton<PlayerManager>.instance.localPlayer.Data.VisualData);
try
{
setPVD(val, data);
}
catch
{
Log("Invalid File Text");
return false;
}
return checkItems(val.ToPlayfabDataString());
}
private void setPVD(PlayerVisualData pvd, string[] data)
{
int num = 0;
for (int i = 0; i < ((Il2CppArrayBase<short>)(object)pvd.ColorationIndexes).Count; i++)
{
((Il2CppArrayBase<short>)(object)pvd.ColorationIndexes)[i] = short.Parse(data[num]);
num++;
}
for (int j = 0; j < ((Il2CppArrayBase<short>)(object)pvd.CustomizationPartIndexes).Count; j++)
{
((Il2CppArrayBase<short>)(object)pvd.CustomizationPartIndexes)[j] = short.Parse(data[num]);
num++;
}
for (int k = 0; k < ((Il2CppArrayBase<short>)(object)pvd.OtherCustomizationIndexes).Count; k++)
{
((Il2CppArrayBase<short>)(object)pvd.OtherCustomizationIndexes)[k] = short.Parse(data[num]);
num++;
}
for (int l = 0; l < ((Il2CppArrayBase<short>)(object)pvd.TextureCustomizationIndexes).Count; l++)
{
((Il2CppArrayBase<short>)(object)pvd.TextureCustomizationIndexes)[l] = short.Parse(data[num]);
num++;
}
for (int m = 0; m < ((Il2CppArrayBase<short>)(object)pvd.TextureOpacityIndexes).Count; m++)
{
((Il2CppArrayBase<short>)(object)pvd.TextureOpacityIndexes)[m] = short.Parse(data[num]);
num++;
}
for (int n = 0; n < ((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes).Count; n++)
{
((Il2CppArrayBase<short>)(object)pvd.WeightAdjustementIndexes)[n] = short.Parse(data[num]);
num++;
}
}
private void setPVD(PlayerVisualData pvdTo, PlayerVisualData pvdFrom)
{
for (int i = 0; i < ((Il2CppArrayBase<short>)(object)pvdTo.ColorationIndexes).Count; i++)
{
((Il2CppArrayBase<short>)(object)pvdTo.ColorationIndexes)[i] = ((Il2CppArrayBase<short>)(object)pvdFrom.ColorationIndexes)[i];
}
for (int j = 0; j < ((Il2CppArrayBase<short>)(object)pvdTo.CustomizationPartIndexes).Count; j++)
{
((Il2CppArrayBase<short>)(object)pvdTo.CustomizationPartIndexes)[j] = ((Il2CppArrayBase<short>)(object)pvdFrom.CustomizationPartIndexes)[j];
}
for (int k = 0; k < ((Il2CppArrayBase<short>)(object)pvdTo.OtherCustomizationIndexes).Count; k++)
{
((Il2CppArrayBase<short>)(object)pvdTo.OtherCustomizationIndexes)[k] = ((Il2CppArrayBase<short>)(object)pvdFrom.OtherCustomizationIndexes)[k];
}
for (int l = 0; l < ((Il2CppArrayBase<short>)(object)pvdTo.TextureCustomizationIndexes).Count; l++)
{
((Il2CppArrayBase<short>)(object)pvdTo.TextureCustomizationIndexes)[l] = ((Il2CppArrayBase<short>)(object)pvdFrom.TextureCustomizationIndexes)[l];
}
for (int m = 0; m < ((Il2CppArrayBase<short>)(object)pvdTo.TextureOpacityIndexes).Count; m++)
{
((Il2CppArrayBase<short>)(object)pvdTo.TextureOpacityIndexes)[m] = ((Il2CppArrayBase<short>)(object)pvdFrom.TextureOpacityIndexes)[m];
}
for (int n = 0; n < ((Il2CppArrayBase<short>)(object)pvdTo.WeightAdjustementIndexes).Count; n++)
{
((Il2CppArrayBase<short>)(object)pvdTo.WeightAdjustementIndexes)[n] = ((Il2CppArrayBase<short>)(object)pvdFrom.WeightAdjustementIndexes)[n];
}
}
private bool checkItems(string tempPVDEconomyDataString)
{
string[] array = tempPVDEconomyDataString.Split(':');
bool flag = true;
for (int i = 0; i < array.Length; i++)
{
if (i == 0 || i == 5)
{
continue;
}
string[] array2 = array[i].Split(",");
string[] array3 = array2;
foreach (string text in array3)
{
if (!Singleton<PlayerManager>.instance.localPlayer.Data.EconomyData.ReceivedItems.Contains(text))
{
flag = false;
Log("Item Not Redeemed");
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
return false;
}
private void mapInit()
{
if (currentScene == "Gym")
{
Save();
}
}
private void loadFileTexts()
{
foreach (string pendingFile in pendingFiles)
{
string item = File.ReadAllText(pendingFile);
pendingFilesTexts.Add(item);
}
}
}
}