Projektdateien hinzufügen.

This commit is contained in:
pan.codes 2024-04-03 21:28:56 +02:00
parent 48cca1f3cd
commit 5a2f9977ca
8 changed files with 655 additions and 0 deletions

View file

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34408.163
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMSModLogOutputAnalyzer", "SMSModLogOutputAnalyzer\SMSModLogOutputAnalyzer.csproj", "{A8BD5FB2-A344-4DD2-99A8-7608053A32FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A8BD5FB2-A344-4DD2-99A8-7608053A32FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8BD5FB2-A344-4DD2-99A8-7608053A32FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8BD5FB2-A344-4DD2-99A8-7608053A32FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8BD5FB2-A344-4DD2-99A8-7608053A32FD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CE2EE494-49E9-4F2F-B29C-A3D7EEB7832B}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,243 @@
using Discord;
using Discord.Interactions;
using System.Text.RegularExpressions;
namespace SMSModLogOutputAnalyzer
{
public class CommandModule : InteractionModuleBase
{
public static List<string> KnownMelonLoaderMods = new List<string>
{
};
public static List<string> KnownBepInExMods = new List<string>
{
"NightShift.dll",
"PermaDay.dll",
"NoMoreDoors.dll",
"UnrestrictedPlacement.dll",
"DisableShelves.dll",
"ChangeCurrency.dll",
"SaveOnQuit.dll",
"CashOnly.dll",
"CardOnly.dll",
"QuieterCars.dll",
"PauseWithBox.dll",
"BoxPause.dll",
"PortableScanner.dll",
"SmartPocketPoxes.dll"
};
public void Log(string log)
{
Program.Log(new LogMessage(LogSeverity.Info, "CommandModule", log));
}
public override void OnModuleBuilding(InteractionService commandService, ModuleInfo module)
{
Console.WriteLine("Building module");
}
[MessageCommand("Analyze Log")]
public async Task Analyze(IMessage message)
{
if(message.Attachments.Count > 0)
{
await Upload((Attachment)message.Attachments.First());
} else
{
await RespondAsync("Message has no attachment.", ephemeral: true);
}
}
[SlashCommand("upload", "Upload a LogOutput.log file for analysis.")]
public async Task Upload([Summary(description: "Please upload your LogOutput.log file. It is found inside the BepInEx folder in your game directory.")] Attachment file)
{
try
{
Log("Received file upload.");
var http = new HttpClient();
var text = await http.GetStringAsync(file.Url);
if(Program.AnalysisCache.ContainsKey(text))
{
await RespondAsync(ephemeral: true, text: "This log file has already been analysed [here](" + Program.AnalysisCache[text].GetJumpUrl() + ").");
return;
}
await DeferAsync();
Log(text);
var textLines = text.Split('\n').Select(x => x.Trim()).ToArray();
var embedBuilder = new EmbedBuilder();
embedBuilder.WithAuthor(Context.User);
embedBuilder.WithFooter(Program.Footer);
Dictionary<string, List<Tuple<bool?, string, string>>> values = new();
var lines = FindLines(textLines,
"[Message:MelonLoader] Game Version: ",
"[Message:MelonLoader] Unity Version: ",
"[Message: BepInEx] BepInEx ",
"[Info : BepInEx] Loading [",
"[Message:MelonLoader] Assembly: ",
"[Info : Unity Log] System.EntryPointNotFoundException: SteamAPI_SteamInput_v001",
"[Message: File Tree] ");
Log("Initial analysis complete.");
values[":page_facing_up: Game Version"] = new List<Tuple<bool?, string, string>> { new(null, "", lines["[Message:MelonLoader] Game Version: "][0].Item1) };
values[":diamond_shape_with_a_dot_inside: Unity Version"] = new List<Tuple<bool?, string, string>> { new(null, "", lines["[Message:MelonLoader] Unity Version: "][0].Item1) };
values[":tools: BepInEx Version"] = new List<Tuple<bool?, string, string>> { new(null, "", lines["[Message: BepInEx] BepInEx "][0].Item1.Split(" - ")[0]) };
List<Tuple<bool?, string, string>> part = new();
foreach (var mod in lines["[Info : BepInEx] Loading ["])
{
var match = Regex.Match(mod.Item1, "(.+) ((\\d+\\.)+\\d+)\\]");
part.Add(new(null, "", "**" + match.Groups[1] + "** " + match.Groups[2]));
}
values[":tools: Loaded BepInEx Mods"] = part;
part = new();
foreach (var mod in lines["[Message:MelonLoader] Assembly: "])
{
string line = textLines[mod.Item2 - 1];
var match = Regex.Match(line, "\\[.+\\] (.+) v((\\d+\\.)+\\d+).+");
part.Add(new(null, "", "**" + match.Groups[1] + "** " + match.Groups[2]));
}
values[":melon: Loaded MelonLoader Mods"] = part;
part = new();
if (lines["[Info : Unity Log] System.EntryPointNotFoundException: SteamAPI_SteamInput_v001"].Count > 0) part.Add(new(false, "", "Steam Entry Point not found"));
values[":loudspeaker: Common Errors"] = part;
part = new();
List<string> filetree = new();
Dictionary<int, string> depths = new();
values[":file_folder: Install Directory"] = new List<Tuple<bool?, string, string>> { new(null, "", lines["[Message: File Tree] "][0].Item1) };
foreach (var lineTuple in lines["[Message: File Tree] "])
{
string line = lineTuple.Item1;
if (!line.Contains("--")) continue;
int depth = 0;
while (line.StartsWith("| ") || line.StartsWith(" "))
{
depth++;
line = line.Substring(4);
}
line = line.Split("-- ")[1].Split(" [")[0];
if (line == "(contents not shown)") continue;
depths[depth] = line;
while (depth > 0)
{
depth--;
line = depths[depth] + "\\" + line;
}
filetree.Add(line);
}
foreach (var filename in filetree) Log(filename);
foreach (var bepinexmod in filetree.Where(x => x.StartsWith("BepInEx\\plugins") && x.EndsWith(".dll")))
{
var mod = bepinexmod.Substring(16);
if (KnownMelonLoaderMods.Contains(mod.Split('\\').Last().Trim()))
{
part.Add(new(false, "Known MelonLoader Mod", mod));
}
else
{
part.Add(new(null, "", mod));
}
}
values[":file_folder: DLL Files in BepInEx/plugins"] = part;
part = new();
foreach (var melonmod in filetree.Where(x => x.StartsWith("MLLoader\\Mods") && x.EndsWith(".dll")))
{
var mod = melonmod.Substring(14);
if (KnownBepInExMods.Contains(mod.Split('\\').Last().Trim()))
{
part.Add(new(false, "Known BepInEx Mod", mod));
}
else
{
part.Add(new(null, "", mod));
}
}
values[":file_folder: DLL Files in MLLoader\\Mods"] = part;
part = new();
var downloadButton = new ComponentBuilder();
downloadButton.WithButton(label: "Download LogOutput.log", url: file.Url, style: ButtonStyle.Link);
var fields = values.Where(x => !string.IsNullOrEmpty(x.Key) && x.Value.Count > 0)
.Select(x => new EmbedFieldBuilder
{
IsInline = false,
Name = x.Key,
Value = string.Join("\n", x.Value.Select(y =>
{
string value = "";
if (y.Item1.HasValue) value = "❌";
if (y.Item1.HasValue && y.Item1.Value) value = "✅";
value += " " + y.Item3;
if (!string.IsNullOrEmpty(y.Item2)) value += " (" + y.Item2 + ")";
return value;
}))
});
foreach (var field in fields) Log(field.Name + ", " + field.Value);
embedBuilder.WithFields(fields);
embedBuilder.WithColor(Color.DarkBlue);
var embed = embedBuilder.Build();
var message = await ModifyOriginalResponseAsync(func => { func.Embeds = new[] { embed }; func.Components = downloadButton.Build(); });
Program.AnalysisCache.Add(text, message);
}
catch (Exception e)
{
Log(e.Message);
Log(e.Data.ToString());
Log(e.StackTrace);
}
}
public static Dictionary<string, List<Tuple<string, int>>> FindLines(string[] file, params string[] lines)
{
Dictionary<string, List<Tuple<string, int>>> results = new();
int i = 0;
foreach (var start in lines) results[start] = new();
foreach (var line in file)
{
foreach (var start in lines)
{
if (line.ToLower().StartsWith(start.ToLower())) results[start].Add(new(line.Substring(start.Length), i));
}
i++;
}
return results;
}
[SlashCommand("troubleshoot", "Starts the troubleshooting assistant.")]
[RequireUserPermission(GuildPermission.ManageChannels)]
public async Task Troubleshoot()
{
await RespondAsync("Posting", ephemeral: true);
await Context.Channel.SendMessageAsync(embed: new EmbedBuilder()
.WithTitle("Troubleshooting Assistant")
.WithDescription("Press the button below to be guided through our troubleshooting assistant. Hopefully it can help you with getting mods working.")
.WithFooter(Program.Footer)
.Build(),
components: new ComponentBuilder()
.WithButton("Start", "troubleshoot:root", ButtonStyle.Success)
.Build());
}
[ComponentInteraction("troubleshoot:*")]
public async Task TroubleshootButton(string node)
{
Flowchart.FlowchartNode fcnode = Program.Troubleshooting.Nodes.Find(x => x.Name == node);
if (fcnode == null) return;
var connections = Program.Troubleshooting.Connections.Where(x => x.FromName == node);
var cmpb = new ComponentBuilder();
foreach (var conn in connections) cmpb.WithButton(conn.Text, "troubleshoot:" + conn.ToName, conn.Text == "Yes" ? ButtonStyle.Success : conn.Text == "No" ? ButtonStyle.Danger : ButtonStyle.Primary);
await RespondAsync(embed: new EmbedBuilder()
.WithTitle(fcnode.Text)
.WithDescription(fcnode.Description)
.WithFooter(Program.Footer)
.Build(), components: cmpb.Build(), ephemeral: true);
}
}
}

View file

@ -0,0 +1,53 @@
namespace SMSModLogOutputAnalyzer
{
internal class Flowchart
{
public static Flowchart Parse(string file) => Parse(file.Split('\n'));
public static Flowchart Parse(string[] lines)
{
Flowchart flowchart = new();
foreach (var line in lines)
{
if (line.Contains("-->"))
{
var fc = new FlowchartConnection();
fc.FromName = line.Split("-->")[0].Trim().ToLower();
if (line.Contains("|"))
{
fc.ToName = line.Split('|')[2].Trim().ToLower();
fc.Text = line.Split('|')[1].Trim().Replace("\\n", "").Replace("]", "");
} else
{
fc.ToName = line.Split("-->")[1].Trim().ToLower();
fc.Text = "Next";
}
flowchart.Connections.Add(fc);
}
else
{
string name = line.Split('[')[0].Trim().ToLower();
string text = line.Split('[')[1].Split("<sub>")[0].Replace("\\n", "").Replace("]", "");
string description = line.Contains("<sub>") ? line.Split("<sub>")[1].Trim().Trim(']').Replace("\\n", "\n") : "";
flowchart.Nodes.Add(new FlowchartNode { Name = name, Text = text, Description = description });
}
}
return flowchart;
}
public class FlowchartNode
{
public string Name { get; set; }
public string Text { get; set; }
public string Description { get; set; }
}
public class FlowchartConnection
{
public string FromName { get; set; }
public string ToName { get; set; }
public string Text { get; set; }
}
public List<FlowchartNode> Nodes { get; set; } = new();
public List<FlowchartConnection> Connections { get; set; } = new();
}
}

View file

@ -0,0 +1,60 @@
using Discord.WebSocket;
using Discord;
using Discord.Interactions;
using System.Reflection;
using System;
namespace SMSModLogOutputAnalyzer
{
internal static class Program
{
private static DiscordSocketClient _client;
public static Flowchart Troubleshooting;
public const string Footer = "SMS Mods Bot • Made by BratPfanneTV, for Modded Supermarket Simulator (Unofficial)";
public static Dictionary<string, IMessage> AnalysisCache = new();
public static async Task Main()
{
Troubleshooting = Flowchart.Parse(Properties.Resources.Flowchart);
_client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Debug });
_client.Log += Log;
// You can assign your bot token to a string, and pass that in to connect.
// This is, however, insecure, particularly if you plan to have your code hosted in a public repository.
var token = "MTIyNDgxNjA3OTMwMjQzMDgwMA.GJA8Al.ZeWh0sejaF7MX_v7_gSLzajcVCOiKhLqJNswlI";
_client.Ready += _client_Ready;
// Some alternative options would be to keep your token in an Environment Variable or a standalone file.
// var token = Environment.GetEnvironmentVariable("NameOfYourEnvironmentVariable");
// var token = File.ReadAllText("token.txt");
// var token = JsonConvert.DeserializeObject<AConfigurationClass>(File.ReadAllText("config.json")).Token;
await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();
// Block this task until the program is closed.
await Task.Delay(-1);
}
private static async Task _client_Ready()
{
var server = (ulong)652484929950842881;
var _interactionService = new InteractionService(_client.Rest);
var module = await _interactionService.AddModuleAsync<CommandModule>(null);
await _interactionService.AddModulesGloballyAsync(true, module);
_client.InteractionCreated += async (x) =>
{
var ctx = new SocketInteractionContext(_client, x);
await _interactionService.ExecuteCommandAsync(ctx, null);
};
}
internal static Task Log(LogMessage msg)
{
Console.WriteLine(msg.ToString());
return Task.CompletedTask;
}
}
}

View file

@ -0,0 +1,80 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SMSModLogOutputAnalyzer.Properties {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SMSModLogOutputAnalyzer.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Start[Please follow through this flowchart to attempt to fix any issues you&apos;re having on your own.\nIf everything starts working as expected at any point as you go through this, that&apos;s great!]
///Start --&gt; Root
///Root[Is your mod made for MelonLoader or BepInEx?\n&lt;sub&gt;This should be mentioned in the mod&apos;s description]
///Root --&gt;|BepInEx| IsBepInEx
///Root --&gt;|MelonLoader| IsMelonLoader
///Root --&gt;|Not mentioned| NotMentioned
///IsBepInEx[Is Tobey&apos;s BepInEx Pack installed?\n]
///NotMentioned[Are you sure?]
///IsMelonLoade [Rest der Zeichenfolge wurde abgeschnitten]&quot;; ähnelt.
/// </summary>
internal static string Flowchart {
get {
return ResourceManager.GetString("Flowchart", resourceCulture);
}
}
}
}

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Flowchart" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Flowchart.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View file

@ -0,0 +1,41 @@
Start[Please follow through this flowchart to attempt to fix any issues you're having on your own.\nIf everything starts working as expected at any point as you go through this, that's great!]
Start --> Root
Root[Is your mod made for MelonLoader or BepInEx?\n<sub>This should be mentioned in the mod's description]
Root -->|BepInEx| IsBepInEx
Root -->|MelonLoader| IsMelonLoader
Root -->|Not mentioned| NotMentioned
IsBepInEx[Is Tobey's BepInEx Pack installed?\n]
NotMentioned[Are you sure?]
IsMelonLoader[Is MelonLoader installed?]
IsBepInEx -->|No| InstallBepInEx
IsBepInEx -->|Yes| MLConflict
MLConflict[<sub>Did you install MelonLoader on its own either before or after installing Tobey's BepInEx Pack?]
NotMentioned -->|Yes| ComeGetHelp
IsMelonLoader -->|No| InstallBepInEx
IsMelonLoader -->|Yes| UpdateLoader
InstallBepInEx[Please install:\n<sub>[Tobey's BepInEx x MelonLoader Pack for Supermarket Simulator](https://www.nexusmods.com/supermarketsimulator/mods/9)]
UpdateLoader[Is your mod loader on the newest available version?]
ComeGetHelp[Alright then, you're welcome to ask for help.<sub>Do so in <#1219414924896370739>.\nPlease make sure you have any relevant information about your issue available.]
UpdateLoader -->|No| PleaseUpdate1
UpdateLoader -->|Yes| UpdateGame
PleaseUpdate1[Please update your mod loader.\n<sub>Things may often not work as expected if everything isn't updated.]
PleaseUpdate2[Please update the game.\n<sub>Things may often not work as expected if everything isn't updated.]
PleaseUpdate3[Please update the mod.\n<sub>Things may often not work as expected if everything isn't updated.]
UpdateGame[Is the game itself on the latest version?\n<sub>Mods are always made for the latest version of the game, so if you've not updated, mods may not function.]
UpdateMod[Is the mod you are trying to use on the latest version as well?\n<sub>Especially consider that after the game itself updates, mods may often break and in need of fixes.]
UpdateGame -->|No| PleaseUpdate2
UpdateGame -->|Yes| UpdateMod
UpdateMod -->|No| PleaseUpdate3
PleaseUpdate1 -->|I did and there's still a problem| UpdateGame
PleaseUpdate2 -->|I did and there's still a problem| UpdateMod
PleaseUpdate3 -->|I did and there's still a problem| DeleteConfig
InstallBepInEx -->|I did and there's still a problem| UpdateGame
UpdateMod -->|Yes| DeleteConfig
MLConflict -->|Yes| MLConflict2
MLConflict -->|No| UpdateLoader
DeleteConfig[Delete the Config\n<sub>At this point, please try to delete the mod's config file. It is located in one of these paths:\nBepInEx/config/ModName.cfg\nUserData/ModName.cfg\nMLLoader/UserData/ModName.cfg]
DeleteConfig -->|I did and there's still a problem| ComeGetHelp
DeleteConfig -->|There is no config file| NotMentioned
MLConflict2[Having standalone MelonLoader installed alongside the BepInEx x MelonLoader pack often poses an issue.<sub>Please make sure to completely uninstall standalone MelonLoader, as the Pack supports mods for both loaders.]
MLConflict2 -->|I'm not sure how to do that| ComeGetHelp
MLConflict2 -->|I did and there's still a problem| UpdateLoader

View file

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.14.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>