First commit

This commit is contained in:
Assistant 2019-04-22 02:41:43 -04:00
parent 63198d7ab9
commit 021d90690b
29 changed files with 2184 additions and 0 deletions

25
ModAssistant.sln Normal file
View file

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModAssistant", "ModAssistant\ModAssistant.csproj", "{6A224B82-40DA-40B3-94DC-EFBEC2BDDA39}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6A224B82-40DA-40B3-94DC-EFBEC2BDDA39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A224B82-40DA-40B3-94DC-EFBEC2BDDA39}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A224B82-40DA-40B3-94DC-EFBEC2BDDA39}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A224B82-40DA-40B3-94DC-EFBEC2BDDA39}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {ACC0D20B-78C5-40AC-BF48-553C41D9987B}
EndGlobalSection
EndGlobal

42
ModAssistant/App.config Normal file
View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="ModAssistant.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="ModAssistant.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<userSettings>
<ModAssistant.Properties.Settings>
<setting name="InstallFolder" serializeAs="String">
<value />
</setting>
<setting name="StoreType" serializeAs="String">
<value />
</setting>
<setting name="SaveSelected" serializeAs="String">
<value>False</value>
</setting>
<setting name="CheckInstalled" serializeAs="String">
<value>False</value>
</setting>
<setting name="SavedMods" serializeAs="String">
<value>False</value>
</setting>
<setting name="Agreed" serializeAs="String">
<value>False</value>
</setting>
</ModAssistant.Properties.Settings>
<ModAssistant.Settings1>
<setting name="InstallFolder" serializeAs="String">
<value />
</setting>
<setting name="StoreVariant" serializeAs="String">
<value />
</setting>
</ModAssistant.Settings1>
</userSettings>
</configuration>

9
ModAssistant/App.xaml Normal file
View file

@ -0,0 +1,9 @@
<Application x:Class="ModAssistant.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DispatcherUnhandledException="Application_DispatcherUnhandledException"
Startup="Application_Startup">
<Application.Resources>
</Application.Resources>
</Application>

58
ModAssistant/App.xaml.cs Normal file
View file

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using ModAssistant;
namespace ModAssistant
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public static string BeatSaberInstallDirectory;
public static string BeatSaberInstallType;
public static bool SaveModSelection;
public static bool CheckInstalledMods;
public static List<string> SavedMods = ModAssistant.Properties.Settings.Default.SavedMods.Split(',').ToList();
private void Application_Startup(object sender, StartupEventArgs e)
{
BeatSaberInstallDirectory = Utils.GetInstallDir();
BeatSaberInstallType = ModAssistant.Properties.Settings.Default.StoreType;
SaveModSelection = ModAssistant.Properties.Settings.Default.SaveSelected;
//CheckInstalledMods = ModAssistant.Properties.Settings.Default.CheckInstalled;
if (e.Args.Length == 0)
{
MainWindow window = new MainWindow();
window.Show();
}
else
{
ArgumentHandler(e.Args);
}
}
private void ArgumentHandler(string[] Args)
{
Utils.SendNotify(Args[0]);
}
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show("An unhandled exception just occurred: " + e.Exception.Message, "Exception", MessageBoxButton.OK, MessageBoxImage.Warning);
e.Handled = true;
}
public void RegisterOneClickInstalls ()
{
}
}
}

View file

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace ModAssistant
{
class Diagnostics
{
public static string[] ReadFolder(string path, int level = 0)
{
List<string> entries = new List<string>();
foreach (string file in Directory.GetFileSystemEntries(path))
{
string line = String.Empty;
if (File.Exists(file))
{
line = Utils.CalculateMD5(file) + " " +LevelSeparator(level) + "├─ " + Path.GetFileName(file);
entries.Add(line);
}
else if (Directory.Exists(file))
{
line = Utils.Constants.MD5Spacer + LevelSeparator(level) + "├─ " + Path.GetFileName(file);
entries.Add(line);
foreach (string entry in ReadFolder(file.Replace(@"\", @"\\"), level + 1))
{
//MessageBox.Show(entry);
entries.Add(entry);
}
}
else
{
MessageBox.Show("! " + file);
}
}
if (entries.Count > 0)
entries[entries.Count - 1] = entries[entries.Count - 1].Replace("├", "└");
return entries.ToArray();
}
private static string LevelSeparator(int level)
{
string separator = String.Empty;
for(int i = 0; i < level; i++)
{
separator = separator + "│ ";
}
return separator;
}
}
}

View file

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using ModAssistant.Pages;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModAssistant
{
public class Mod
{
public string name;
public string version;
public string _id;
public string authorId;
public string uploadedDate;
public string updatedDate;
public Author author;
public string description;
public string link;
public string category;
public DownloadLink[] downloads;
public bool required;
public Dependency[] dependencies;
public List<Mod> Dependents = new List<Mod>();
public Mods.ModListItem ListItem;
public class Author
{
public string _id;
public string username;
public string lastLogin;
}
public class DownloadLink
{
public string type;
public string url;
public FileHashes[] hashMd5;
}
public class FileHashes
{
public string hash;
public string file;
}
public class Dependency
{
public string name;
public string _id;
public Mod Mod;
}
}
}

View file

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModAssistant
{
class OneClickInstaller
{
private const string ModelSaberURLPrefix = "https://modelsaber.com/files";
private const string CustomAvatarsFolder = "CustomAvatars";
private const string CustomSabersFolder = "CustomSabers";
private const string CustomPlatformsFolder = "CustomPlatforms";
private static readonly string[] Protocols = new[] { "modsaber" };
public static void InstallAsset(string link)
{
Uri uri = new Uri(link);
if (!Protocols.Contains(uri.Scheme)) return;
}
private static bool DownloadAsset(string link, string folder)
{
string BeatSaberPath = "";
if (string.IsNullOrEmpty(BeatSaberPath))
{
Utils.SendNotify("Beat Saber installation path not found.");
return false;
}
return false;
}
}
}

View file

@ -0,0 +1,256 @@
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Management;
using ModAssistant.Properties;
namespace ModAssistant
{
public class Utils
{
public class Constants
{
public const string BeatSaberAPPID = "620980";
public const string BeatModsAPIUrl = "https://beatmods.com/api/v1/";
public const string BeatModsURL = "https://beatmods.com";
public const string BeatModsModsOptions = "mod?status=approved";
public const string MD5Spacer = " ";
}
public static void SendNotify(string message, string title = "Mod Assistant")
{
var notification = new System.Windows.Forms.NotifyIcon()
{
Visible = true,
Icon = System.Drawing.SystemIcons.Information,
BalloonTipTitle = title,
BalloonTipText = message
};
notification.ShowBalloonTip(5000);
notification.Dispose();
}
public static string CalculateMD5(string filename)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
public static string GetInstallDir()
{
string InstallDir = null;
InstallDir = Properties.Settings.Default.InstallFolder;
if (!String.IsNullOrEmpty(InstallDir))
{
return InstallDir;
}
InstallDir = GetSteamDir();
if (!String.IsNullOrEmpty(InstallDir))
{
return InstallDir;
}
InstallDir = GetOculusDir();
if (!String.IsNullOrEmpty(InstallDir))
{
return InstallDir;
}
MessageBox.Show("Could not detect your Beat Saber install folder. Please select it manually.");
InstallDir = GetManualDir();
if (!String.IsNullOrEmpty(InstallDir))
{
return InstallDir;
}
return null;
}
public static string SetDir(string directory, string store)
{
App.BeatSaberInstallDirectory = directory;
App.BeatSaberInstallType = store;
Properties.Settings.Default.InstallFolder = directory;
Properties.Settings.Default.StoreType = store;
Properties.Settings.Default.Save();
return directory;
}
public static string GetSteamDir()
{
string SteamInstall = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)?.OpenSubKey("SOFTWARE")?.OpenSubKey("WOW6432Node")?.OpenSubKey("Valve")?.OpenSubKey("Steam")?.GetValue("InstallPath").ToString();
if (String.IsNullOrEmpty(SteamInstall))
{
SteamInstall = Registry.LocalMachine.OpenSubKey("SOFTWARE")?.OpenSubKey("WOW6432Node")?.OpenSubKey("Valve")?.OpenSubKey("Steam")?.GetValue("InstallPath").ToString();
}
if (String.IsNullOrEmpty(SteamInstall)) return null;
string vdf = Path.Combine(SteamInstall, @"steamapps\libraryfolders.vdf");
if (!File.Exists(@vdf)) return null;
Regex regex = new Regex("\\s\"\\d\"\\s+\"(.+)\"");
List<string> SteamPaths = new List<string>();
SteamPaths.Add(Path.Combine(SteamInstall, @"steamapps"));
using (StreamReader reader = new StreamReader(@vdf))
{
string line;
while ((line = reader.ReadLine()) != null)
{
Match match = regex.Match(line);
if (match.Success)
{
SteamPaths.Add(Path.Combine(match.Groups[1].Value.Replace(@"\\", @"\"), @"steamapps"));
}
}
}
regex = new Regex("\\s\"installdir\"\\s+\"(.+)\"");
foreach (string path in SteamPaths)
{
if (File.Exists(Path.Combine(@path, @"appmanifest_" + Constants.BeatSaberAPPID + ".acf")))
{
using (StreamReader reader = new StreamReader(Path.Combine(@path, @"appmanifest_" + Constants.BeatSaberAPPID + ".acf")))
{
string line;
while ((line = reader.ReadLine()) != null)
{
Match match = regex.Match(line);
if (match.Success)
{
if (File.Exists(Path.Combine(@path, @"common", match.Groups[1].Value, "Beat Saber.exe")))
{
return SetDir(Path.Combine(@path, @"common", match.Groups[1].Value), "Steam");
}
}
}
}
}
}
return null;
}
public static string GetOculusDir()
{
string OculusInstall = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)?.OpenSubKey("SOFTWARE")?.OpenSubKey("Wow6432Node")?.OpenSubKey("Oculus VR, LLC")?.OpenSubKey("Oculus")?.OpenSubKey("Config")?.GetValue("InitialAppLibrary").ToString();
if (String.IsNullOrEmpty(OculusInstall)) return null;
if (!String.IsNullOrEmpty(OculusInstall))
{
if (File.Exists(Path.Combine(OculusInstall, @"Software\hyperbolic-magnetism-beat-saber", "Beat Saber.exe")))
{
return SetDir(Path.Combine(OculusInstall + @"Software\hyperbolic-magnetism-beat-saber"), "Oculus");
}
}
// Yoinked this code from Umbranox's Mod Manager. Lot's of thanks and love for Umbra <3
using (RegistryKey librariesKey = Registry.CurrentUser.OpenSubKey("Software")?.OpenSubKey("Oculus VR, LLC")?.OpenSubKey("Oculus")?.OpenSubKey("Libraries"))
{
// Oculus libraries uses GUID volume paths like this "\\?\Volume{0fea75bf-8ad6-457c-9c24-cbe2396f1096}\Games\Oculus Apps", we need to transform these to "D:\Game"\Oculus Apps"
WqlObjectQuery wqlQuery = new WqlObjectQuery("SELECT * FROM Win32_Volume");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wqlQuery);
Dictionary<string, string> guidLetterVolumes = new Dictionary<string, string>();
foreach (ManagementBaseObject disk in searcher.Get())
{
var diskId = ((string)disk.GetPropertyValue("DeviceID")).Substring(11, 36);
var diskLetter = ((string)disk.GetPropertyValue("DriveLetter")) + @"\";
if (!string.IsNullOrWhiteSpace(diskLetter))
{
guidLetterVolumes.Add(diskId, diskLetter);
}
}
// Search among the library folders
foreach (string libraryKeyName in librariesKey.GetSubKeyNames())
{
using (RegistryKey libraryKey = librariesKey.OpenSubKey(libraryKeyName))
{
string libraryPath = (string)libraryKey.GetValue("Path");
string finalPath = Path.Combine(guidLetterVolumes.First(x => libraryPath.Contains(x.Key)).Value, libraryPath.Substring(49), @"Software\hyperbolic-magnetism-beat-saber");
if (File.Exists(Path.Combine(finalPath, "Beat Saber.exe")))
{
return SetDir(finalPath, "Oculus");
}
}
}
}
return null;
}
/*
public static string GetManualDir()
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog()
{
IsFolderPicker = true,
Multiselect = false,
Title = "Select your Beat Saber installation folder"
};
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
return dialog.FileName;
}
return null;
}*/
public static string GetManualDir()
{
var dialog = new Microsoft.Win32.SaveFileDialog()
{
Title = "Select your Beat Saber install folder",
Filter = "Directory|*.this.directory",
FileName = "select"
};
if (dialog.ShowDialog() == true)
{
string path = dialog.FileName;
path = path.Replace("\\select.this.directory", "");
path = path.Replace(".this.directory", "");
if (!System.IO.Directory.Exists(path))
{
System.IO.Directory.CreateDirectory(path);
}
if (File.Exists(Path.Combine(path, "Beat Saber.exe")))
{
string store;
if (File.Exists(Path.Combine(path, "Beat Saber_Data", "Plugins", "steam_api64.dll")))
{
store = "Steam";
}
else
{
store = "Oculus";
}
return SetDir(path, store);
}
}
return null;
}
}
}

View file

@ -0,0 +1,87 @@
<Window x:Class="ModAssistant.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ModAssistant"
mc:Ignorable="d"
Icon="Resources/icon.ico"
Title="Mod Assistant" Width="1280" Height="720">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="65" />
<RowDefinition Height="70" />
<RowDefinition Height="70" />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Button Name="IntroButton" Grid.Row="0" Height="60" Margin="0,0,10,5" Background="white" Click="IntroButton_Click">
<StackPanel Margin="0,8,0,0">
<Image Height="30" Source="Resources/Intro.png" VerticalAlignment="Bottom"></Image>
<TextBlock HorizontalAlignment="Center" Margin="0,0,0,5" VerticalAlignment="Bottom">Intro</TextBlock>
</StackPanel>
</Button>
<Button IsEnabled="false" Name="ModsButton" Grid.Row="1" Height="60" Margin="0,5,10,5" Background="white" Click="ModsButton_Click">
<StackPanel Margin="0,6,0,0">
<Image Height="30" Source="Resources/Mods.png" VerticalAlignment="Bottom"></Image>
<TextBlock HorizontalAlignment="Center" Margin="0,0,0,5" VerticalAlignment="Bottom">Mods</TextBlock>
</StackPanel>
</Button>
<Button Name="AboutButton" Grid.Row="2" Height="60" Margin="0,5,10,5" Background="white" Click="AboutButton_Click">
<StackPanel Margin="0,6,0,0">
<Image Height="30" Source="Resources/About.png" VerticalAlignment="Bottom"></Image>
<TextBlock HorizontalAlignment="Center" Margin="0,0,0,5" VerticalAlignment="Bottom">About</TextBlock>
</StackPanel>
</Button>
<Button Name="OptionsButton" Grid.Row="3" Height="60" Margin="0,5,10,5" Background="white" Click="OptionsButton_Click">
<StackPanel Margin="0,5,0,0">
<Image Height="30" Source="Resources/Options.png" VerticalAlignment="Bottom"></Image>
<TextBlock HorizontalAlignment="Center" Margin="0,0,0,5" VerticalAlignment="Bottom">Options</TextBlock>
</StackPanel>
</Button>
</Grid>
<Frame Grid.Column="1" Name="Main" NavigationUIVisibility="Hidden" />
<Grid Grid.Row="1" Grid.Column="1" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="115" />
<ColumnDefinition Width="115" />
</Grid.ColumnDefinitions>
<TextBlock Name="MainTextBlock" Padding="5" Height="40" VerticalAlignment="Bottom" Background="LightGray" FontSize="20" />
<Button Grid.Column="1" Name="InfoButton" IsEnabled="False" Height="40" Width="100" HorizontalAlignment="Right" Margin="0,10,0,0" Click="InfoButton_Click">
<StackPanel>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Bottom">
Mod Info
</TextBlock>
</StackPanel>
</Button>
<Button Grid.Column="2" Name="InstallButton" IsEnabled="False" Height="40" Width="100" HorizontalAlignment="Right" Margin="0,10,0,0" Click="InstallButton_Click">
<StackPanel>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Bottom">
Install
</TextBlock>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Bottom">
or Update
</TextBlock>
</StackPanel>
</Button>
</Grid>
</Grid>
</Window>

View file

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Net;
using System.IO;
using System.Web.Script.Serialization;
using System.Runtime.Serialization;
using ModAssistant.Pages;
namespace ModAssistant
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static MainWindow Instance;
//private delegate void SetStatusCallback(string message);
//public static Mods ModWindow = new Mods();
public string MainText
{
get
{
return MainTextBlock.Text;
}
set
{
Dispatcher.Invoke(new Action(() => { MainWindow.Instance.MainTextBlock.Text = value; }));
}
}
public MainWindow()
{
InitializeComponent();
Instance = this;
if (Properties.Settings.Default.Agreed)
{
MainWindow.Instance.ModsButton.IsEnabled = true;
}
//Main.Content = Mods.Instance;
Main.Content = Intro.Instance;
}
private void ModsButton_Click(object sender, RoutedEventArgs e)
{
Main.Content = Mods.Instance;
}
private void IntroButton_Click(object sender, RoutedEventArgs e)
{
Main.Content = Intro.Instance;
}
private void AboutButton_Click(object sender, RoutedEventArgs e)
{
Main.Content = About.Instance;
}
private void OptionsButton_Click(object sender, RoutedEventArgs e)
{
Main.Content = Options.Instance;
}
private void InstallButton_Click(object sender, RoutedEventArgs e)
{
Mods.Instance.InstallMods();
}
private void InfoButton_Click(object sender, RoutedEventArgs e)
{
Mods.ModListItem mod = ((Mods.ModListItem)Mods.Instance.ModsListView.SelectedItem);
string infoUrl = mod.ModInfo.link;
if (String.IsNullOrEmpty(infoUrl))
{
MessageBox.Show(mod.ModName + " does not have an info page");
}
else
{
System.Diagnostics.Process.Start(infoUrl);
}
}
}
}

View file

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6A224B82-40DA-40B3-94DC-EFBEC2BDDA39}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>ModAssistant</RootNamespace>
<AssemblyName>ModAssistant</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Management" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Classes\Diagnostics.cs" />
<Compile Include="Pages\Intro.xaml.cs">
<DependentUpon>Intro.xaml</DependentUpon>
</Compile>
<Compile Include="Classes\Mod.cs" />
<Compile Include="Pages\Mods.xaml.cs">
<DependentUpon>Mods.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\About.xaml.cs">
<DependentUpon>About.xaml</DependentUpon>
</Compile>
<Compile Include="Classes\Utils.cs" />
<Page Include="Pages\Intro.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Classes\OneClickInstaller.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Pages\Mods.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\About.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\Options.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Pages\Options.xaml.cs">
<DependentUpon>Options.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>PublicSettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\icon.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\About.png" />
<Resource Include="Resources\Intro.png" />
<Resource Include="Resources\Mods.png" />
<Resource Include="Resources\Options.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,102 @@
<Page x:Class="ModAssistant.Pages.About"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ModAssistant"
mc:Ignorable="d"
d:DesignHeight="629" d:DesignWidth="1182"
Title="About">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Top" HorizontalAlignment="Left" FontSize="24" Margin="0">About Mod Assistant</TextBlock>
<TextBlock Grid.Row="1" TextWrapping="Wrap" Margin="0,5" FontSize="16" >
I'm Assistant, and I made Mod Assistant as an alternative to the
<Hyperlink NavigateUri="https://github.com/beat-saber-modding-group/BeatSaberModInstaller" RequestNavigate="Hyperlink_RequestNavigate">
Mod Manager
</Hyperlink>
and
<Hyperlink NavigateUri="https://github.com/StarGazer1258/BeatDrop" RequestNavigate="Hyperlink_RequestNavigate">
BeatDrop
</Hyperlink>
with a few principles in mind:
</TextBlock>
<TextBlock Grid.Row="2" Margin="15,5" FontSize="16" Text="• Simplicty" />
<TextBlock Grid.Row="3" Margin="15,5" FontSize="16" Text="• Portability" />
<TextBlock Grid.Row="4" Margin="15,5" FontSize="16" Text="• Single Executable" />
<TextBlock Grid.Row="5" Margin="15,5" FontSize="16" Text="• Responsible use" />
<TextBlock TextWrapping="Wrap" Grid.Row="6" Margin="30,5,5,5" FontSize="16">
If you enjoy this program and would like to support me, please visit my
<Hyperlink NavigateUri="https://bs.assistant.moe/Donate/" RequestNavigate="Hyperlink_RequestNavigate">
donation page
</Hyperlink>
or my
<Hyperlink NavigateUri="https://www.patreon.com/AssistantMoe" RequestNavigate="Hyperlink_RequestNavigate">
Patreon
</Hyperlink>
</TextBlock>
<TextBlock Grid.Row="7" Margin="0,10,5,5" FontSize="20" Text="Special Thanks ♥" />
<StackPanel Grid.Row="8" Orientation="Horizontal" HorizontalAlignment="Center">
<StackPanel Margin="5" Orientation="Vertical">
<TextBlock FontSize="20" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center">
<Hyperlink NavigateUri="https://www.vanzeben.ca/" RequestNavigate="Hyperlink_RequestNavigate">
vanZeben
</Hyperlink>
</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">Creating BeatMods</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">The current Mod repository</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">Used by this Installer</TextBlock>
</StackPanel>
<StackPanel Margin="5" Orientation="Vertical">
<TextBlock FontSize="20" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center">
<Hyperlink NavigateUri="https://linkkle.com/umbranoxus" RequestNavigate="Hyperlink_RequestNavigate">
Umbranox
</Hyperlink>
</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">Inspiration</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">Creating the Mod Manager</TextBlock>
</StackPanel>
<StackPanel Margin="5" Orientation="Vertical">
<TextBlock FontSize="20" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center">
<Hyperlink NavigateUri="https://www.jackbaron.com/" RequestNavigate="Hyperlink_RequestNavigate">
lolPants
</Hyperlink>
</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">Inspiration</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">Creating ModSaber</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">The first Mod repository</TextBlock>
<TextBlock FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center">
<Hyperlink NavigateUri="https://www.paypal.me/jackmbaron" RequestNavigate="Hyperlink_RequestNavigate">
Donate
</Hyperlink>
</TextBlock>
</StackPanel>
</StackPanel>
</Grid>
</Page>

View file

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ModAssistant.Pages
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class About : Page
{
public static About Instance = new About();
public About()
{
InitializeComponent();
}
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
}
}

View file

@ -0,0 +1,75 @@
<Page x:Class="ModAssistant.Pages.Intro"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ModAssistant"
mc:Ignorable="d"
d:DesignHeight="629" d:DesignWidth="1182"
Title="Intro">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="48" Margin="0">Welcome to Mod Assistant</TextBlock>
<TextBlock Grid.Row="1" FontWeight="Bold" Text="Please read this page entirely and carefully" Margin="0" FontSize="28" />
<TextBlock Grid.Row="2" Margin="0,5" FontSize="16" TextWrapping="Wrap" Text="By using this program attest to have read and agree to the following terms:" />
<TextBlock Grid.Row="3" Margin="0,5" FontSize="16" TextWrapping="Wrap">
Beat Saber <Bold>does not</Bold> natively support mods. This means:
</TextBlock>
<TextBlock Grid.Row="4" Margin="15,5" FontSize="16" TextWrapping="Wrap">
Mods <Bold>will break</Bold> every update. This is normal, and <Bold>not</Bold> Beat Games' fault.
</TextBlock>
<TextBlock Grid.Row="5" Margin="15,5" FontSize="16" TextWrapping="Wrap">
Mods <Bold>will</Bold> cause bugs and performance issues. This is <Bold>not</Bold> Beat Games' fault.
</TextBlock>
<TextBlock Grid.Row="6" Margin="15,5" FontSize="16" TextWrapping="Wrap">
Mods are made for <Bold>free</Bold> by people in their <Bold>free time.</Bold> Please be patient and understanding.
</TextBlock>
<TextBlock Grid.Row="7" Margin="0,5" FontSize="16" TextWrapping="Wrap">
<Bold>DO NOT</Bold> leave negative reviews because mods broke. This is <Bold>not</Bold> Beat Games' fault. <LineBreak/> They are not trying to kill mods.
</TextBlock>
<TextBlock Grid.Row="8" Margin="0,5" FontSize="16" TextWrapping="Wrap">
If I keep seeing people leave negative reviews <Italic>because</Italic> mods broke, <LineBreak/><Bold>I will personally kill mods with a rusty spoon</Bold>
</TextBlock>
<TextBlock Grid.Row="9" Margin="0,5" FontSize="16" TextWrapping="Wrap">
Please read the Beginners Guide on the
<Hyperlink NavigateUri="https://bsmg.wiki/beginners-guide" RequestNavigate="Hyperlink_RequestNavigate">
Wiki
</Hyperlink>.
</TextBlock>
<StackPanel Margin="10" Grid.Row="10" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Margin="0,0,10,0" Name="Agree" Height="35" Width="100" VerticalAlignment="Center" HorizontalAlignment="Center" Click="Agree_Click">
<TextBlock FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center">
I Agree
</TextBlock>
</Button>
<Button Margin="10,0,0,0" Name="Disagree" Height="35" Width="100" VerticalAlignment="Center" HorizontalAlignment="Center" Click="Disagree_Click">
<TextBlock FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center">
Disagree
</TextBlock>
</Button>
</StackPanel>
</Grid>
</Page>

View file

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ModAssistant.Pages
{
/// <summary>
/// Interaction logic for Intro.xaml
/// </summary>
public partial class Intro : Page
{
public static Intro Instance = new Intro();
public Intro()
{
InitializeComponent();
}
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
private void Disagree_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Closing Application: You did not agree to terms and conditions.");
System.Windows.Application.Current.Shutdown();
}
private void Agree_Click(object sender, RoutedEventArgs e)
{
MainWindow.Instance.ModsButton.IsEnabled = true;
Properties.Settings.Default.Agreed = true;
Properties.Settings.Default.Save();
}
}
}

View file

@ -0,0 +1,56 @@
<Page x:Class="ModAssistant.Pages.Mods"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ModAssistant"
mc:Ignorable="d"
d:DesignHeight="629" d:DesignWidth="1182"
Title="Mods">
<Grid>
<ListView Name="ModsListView" Grid.Column="1" SelectionMode="Single" SelectionChanged="ModsListView_SelectionChanged">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="30">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="ModCheckBox" IsEnabled="{Binding IsEnabled}" Tag="{Binding ModInfo}" IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Checked="ModCheckBox_Checked" Unchecked="ModCheckBox_Unchecked"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding ModName}" />
<GridViewColumn x:Name="InstalledColumn" Header="Installed">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding InstalledVersion}" Foreground="{Binding IsOutdated}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Latest" DisplayMemberBinding="{Binding ModVersion}" />
<GridViewColumn x:Name="DescriptionColumn" Header="Description" Width="750" DisplayMemberBinding="{Binding ModDescription}"/>
<GridViewColumn x:Name="UninstallColumn" Header="Uninstall" Width="70">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Name="Uninstall" Content="Uninstall" Visibility="{Binding CanSeeDelete}" IsEnabled="{Binding CanDelete}" Foreground="Red" Tag="{Binding ModInfo}" Click="Uninstall_Click"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="14" Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
</Page>

View file

@ -0,0 +1,460 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.Compression;
using System.Diagnostics;
using System.Windows.Forms;
namespace ModAssistant.Pages
{
/// <summary>
/// Interaction logic for Mods.xaml
/// </summary>
public sealed partial class Mods : Page
{
public static Mods Instance = new Mods();
public string[] DefaultMods = { "SongLoader", "ScoreSaber", "BeatSaverDownloader" };
public Mod[] ModsList;
public static List<Mod> InstalledMods = new List<Mod>();
public List<string> CategoryNames = new List<string>();
public CollectionView view;
public List<ModListItem> ModList { get; set; }
public Mods()
{
InitializeComponent();
ModList = new List<ModListItem>();
LoadMods();
}
private void RefreshModsList()
{
view.Refresh();
}
private async void LoadMods()
{
if (App.CheckInstalledMods)
{
MainWindow.Instance.MainText = "Checking Installed Mods...";
await Task.Run(() => CheckInstalledMods());
} else
{
InstalledColumn.Width = 0;
UninstallColumn.Width = 0;
DescriptionColumn.Width = 800;
}
MainWindow.Instance.MainText = "Loading Mods...";
await Task.Run(() => PopulateModsList());
ModsListView.ItemsSource = ModList;
view = (CollectionView)CollectionViewSource.GetDefaultView(ModsListView.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("Category");
view.GroupDescriptions.Add(groupDescription);
this.DataContext = this;
RefreshModsList();
MainWindow.Instance.MainText = "Finished Loading Mods.";
MainWindow.Instance.InstallButton.IsEnabled = true;
}
private void CheckInstalledMods()
{
List<string> empty = new List<string>();
CheckInstallDir("Plugins", empty);
CheckInstallDir(@"IPA\Libs", empty);
}
private void CheckInstallDir(string directory, List<string> blacklist)
{
foreach (string file in Directory.GetFileSystemEntries(System.IO.Path.Combine(App.BeatSaberInstallDirectory, directory)))
{
if (File.Exists(file) && System.IO.Path.GetExtension(file) == ".dll")
{
Mod mod = GetModFromHash(Utils.CalculateMD5(file));
if (mod != null)
{
if (!InstalledMods.Contains(mod))
{
InstalledMods.Add(mod);
}
}
}
}
}
private Mod GetModFromHash(string hash)
{
string json = string.Empty;
Mod[] modMatches;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Utils.Constants.BeatModsAPIUrl + "mod?hash=" + hash);
request.AutomaticDecompression = DecompressionMethods.GZip;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
var serializer = new JavaScriptSerializer();
modMatches = serializer.Deserialize<Mod[]>(reader.ReadToEnd());
}
if (modMatches.Length == 0)
return null;
return modMatches[0];
}
public void PopulateModsList()
{
string json = string.Empty;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Utils.Constants.BeatModsAPIUrl + Utils.Constants.BeatModsModsOptions);
request.AutomaticDecompression = DecompressionMethods.GZip;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
var serializer = new JavaScriptSerializer();
ModsList = serializer.Deserialize<Mod[]>(reader.ReadToEnd());
}
foreach (Mod mod in ModsList)
{
bool preSelected = mod.required;
if (DefaultMods.Contains(mod.name) || (App.SaveModSelection && App.SavedMods.Contains(mod.name)))
{
preSelected = true;
if(!App.SavedMods.Contains(mod.name))
{
App.SavedMods.Add(mod.name);
}
}
RegisterDependencies(mod);
ModListItem ListItem = new ModListItem()
{
IsSelected = preSelected,
IsEnabled = !mod.required,
ModName = mod.name,
ModVersion = mod.version,
ModDescription = mod.description.Replace('\n', ' '),
ModInfo = mod,
Category = mod.category
};
foreach (Mod installedMod in InstalledMods)
{
if (mod.name == installedMod.name)
{
ListItem.IsInstalled = true;
ListItem.InstalledVersion = installedMod.version;
break;
}
}
mod.ListItem = ListItem;
ModList.Add(ListItem);
}
foreach (Mod mod in ModsList)
{
ResolveDependencies(mod);
}
}
public async void InstallMods ()
{
MainWindow.Instance.InstallButton.IsEnabled = false;
string installDirectory = App.BeatSaberInstallDirectory;
foreach (Mod mod in ModsList)
{
if (mod.name.ToLower() == "bsipa")
{
MainWindow.Instance.MainText = $"Installing {mod.name}...";
await Task.Run(() => InstallMod(mod, installDirectory));
MainWindow.Instance.MainText = $"Installed {mod.name}.";
await Task.Run(() =>
Process.Start(new ProcessStartInfo
{
FileName = System.IO.Path.Combine(installDirectory, "IPA.exe"),
WorkingDirectory = installDirectory,
Arguments = "-n"
}).WaitForExit()
);
}
else if(mod.ListItem.IsSelected)
{
MainWindow.Instance.MainText = $"Installing {mod.name}...";
await Task.Run(() => InstallMod(mod, System.IO.Path.Combine(installDirectory, @"IPA\Pending")));
MainWindow.Instance.MainText = $"Installed {mod.name}.";
}
}
MainWindow.Instance.MainText = "Finished installing mods.";
MainWindow.Instance.InstallButton.IsEnabled = true;
}
private void InstallMod (Mod mod, string directory)
{
string downloadLink = null;
foreach (Mod.DownloadLink link in mod.downloads)
{
if (link.type == "universal")
{
downloadLink = link.url;
break;
} else if (link.type.ToLower() == App.BeatSaberInstallType.ToLower())
{
downloadLink = link.url;
break;
}
}
if (String.IsNullOrEmpty(downloadLink))
{
System.Windows.MessageBox.Show($"Could not find download link for {mod.name}");
return;
}
using (MemoryStream stream = new MemoryStream(DownloadMod(Utils.Constants.BeatModsURL + mod.downloads[0].url)))
{
using (ZipArchive archive = new ZipArchive(stream))
{
foreach (ZipArchiveEntry file in archive.Entries)
{
string fileDirectory = System.IO.Path.GetDirectoryName(System.IO.Path.Combine(directory, file.FullName));
if (!Directory.Exists(fileDirectory))
Directory.CreateDirectory(fileDirectory);
if(!String.IsNullOrEmpty(file.Name))
file.ExtractToFile(System.IO.Path.Combine(directory, file.FullName), true);
}
}
}
}
private byte[] DownloadMod (string link)
{
byte[] zip = new WebClient().DownloadData(link);
return zip;
}
private void RegisterDependencies(Mod dependent)
{
if (dependent.dependencies.Length == 0)
return;
foreach (Mod mod in ModsList)
{
foreach (Mod.Dependency dep in dependent.dependencies)
{
if (dep.name == mod.name)
{
dep.Mod = mod;
mod.Dependents.Add(dependent);
}
}
}
}
private void ResolveDependencies(Mod dependent)
{
if (dependent.ListItem.IsSelected && dependent.dependencies.Length > 0)
{
foreach (Mod.Dependency dependency in dependent.dependencies)
{
if (dependency.Mod.ListItem.IsEnabled)
{
dependency.Mod.ListItem.PreviousState = dependency.Mod.ListItem.IsSelected;
dependency.Mod.ListItem.IsSelected = true;
dependency.Mod.ListItem.IsEnabled = false;
ResolveDependencies(dependency.Mod);
}
}
}
}
private void UnresolveDependencies(Mod dependent)
{
if (!dependent.ListItem.IsSelected && dependent.dependencies.Length > 0)
{
foreach (Mod.Dependency dependency in dependent.dependencies)
{
if (!dependency.Mod.ListItem.IsEnabled)
{
bool needed = false;
foreach (Mod dep in dependency.Mod.Dependents)
{
if (dep.ListItem.IsSelected)
{
needed = true;
break;
}
}
if (!needed && !dependency.Mod.required)
{
dependency.Mod.ListItem.IsSelected = dependency.Mod.ListItem.PreviousState;
dependency.Mod.ListItem.IsEnabled = true;
UnresolveDependencies(dependency.Mod);
}
}
}
}
}
private void ModCheckBox_Checked(object sender, RoutedEventArgs e)
{
Mod mod = ((sender as System.Windows.Controls.CheckBox).Tag as Mod);
mod.ListItem.IsSelected = true;
ResolveDependencies(mod);
App.SavedMods.Add(mod.name);
Properties.Settings.Default.SavedMods = String.Join(",", App.SavedMods.ToArray());
Properties.Settings.Default.Save();
RefreshModsList();
}
private void ModCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
Mod mod = ((sender as System.Windows.Controls.CheckBox).Tag as Mod);
mod.ListItem.IsSelected = false;
UnresolveDependencies(mod);
App.SavedMods.Remove(mod.name);
Properties.Settings.Default.SavedMods = String.Join(",", App.SavedMods.ToArray());
Properties.Settings.Default.Save();
RefreshModsList();
}
public class Category
{
public string CategoryName { get; set; }
public List<ModListItem> Mods = new List<ModListItem>();
}
public class ModListItem
{
public string ModName { get; set; }
public string ModVersion { get; set; }
public string ModDescription { get; set; }
public bool PreviousState { get; set; }
public bool IsEnabled { get; set; }
public bool IsSelected { get; set; }
public Mod ModInfo { get; set; }
public string Category { get; set; }
public bool IsInstalled { get; set; }
private string _installedVersion { get; set; }
public string InstalledVersion {
get
{
if (String.IsNullOrEmpty(_installedVersion) || !IsInstalled)
{
return "-";
}
else
{
return _installedVersion;
}
}
set
{
_installedVersion = value;
}
}
public string IsOutdated {
get
{
if (IsInstalled)
{
if (InstalledVersion == ModVersion)
{
return "Green"; //green
} else
{
return "Red"; //red
}
}
else
{
return "Black"; //grey
}
}
}
public bool CanDelete
{
get
{
return (!ModInfo.required && IsInstalled);
}
}
public string CanSeeDelete
{
get
{
if (!ModInfo.required && IsInstalled)
return "Visible";
else
return "Hidden";
}
}
}
private void ModsListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MainWindow.Instance.InfoButton.IsEnabled = true;
}
private void Uninstall_Click(object sender, RoutedEventArgs e)
{
Mod mod = ((sender as System.Windows.Controls.Button).Tag as Mod);
if (System.Windows.Forms.MessageBox.Show($"Uninstall {mod.name}?", $"Are you sure you want to remove {mod.name}?\nThis can break other of your mods.", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
Mod.DownloadLink links = null;
foreach (Mod.DownloadLink link in mod.downloads)
{
if (link.type.ToLower() == "universal" || link.type.ToLower() == App.BeatSaberInstallType.ToLower())
{
links = link;
break;
}
}
foreach (Mod.FileHashes files in links.hashMd5)
{
File.Delete(System.IO.Path.Combine(App.BeatSaberInstallDirectory, files.file));
}
mod.ListItem.IsInstalled = false;
mod.ListItem.InstalledVersion = null;
}
}
}
}

View file

@ -0,0 +1,67 @@
<Page x:Class="ModAssistant.Pages.Options"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ModAssistant.Pages"
mc:Ignorable="d"
d:DesignHeight="629" d:DesignWidth="1182"
Title="Options">
<Page.Resources>
</Page.Resources>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Margin="15,5,5,5" Text="Settings" FontSize="24" FontWeight="Bold" HorizontalAlignment="Left"/>
<TextBlock Grid.Row="1" Margin="5" Text="Install Folder" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16"/>
<Border Grid.ColumnSpan="2" Grid.Row="2" Margin="5" Background="LightGray" Height="30" MinWidth="450" >
<TextBlock Margin="5" Text="{Binding InstallDirectory}" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="16"/>
</Border>
<Button Grid.Row="2" Grid.Column="2" Margin="3" Height="30" Width="80" Content="Select Folder" Click="Button_Click"/>
<TextBlock Grid.Row="3" Margin="5" Text="Save Selected Mods" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="3" Grid.Column="1" Name="SaveSelected" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding SaveSelection, Mode=TwoWay}" Checked="SaveSelected_Checked" Unchecked="SaveSelected_Unchecked"/>
<TextBlock Grid.Row="4" Margin="5" Text="Check Installed Mods" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="4" Grid.Column="1" Name="CheckInstalled" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding CheckInstalledMods, Mode=TwoWay}" Checked="CheckInstalled_Checked" Unchecked="CheckInstalled_Unchecked"/>
<StackPanel Grid.Row="5" Margin="20,0,0,0" Background="LightYellow" HorizontalAlignment="Left">
<TextBlock Margin="5,5,5,0" Text="Will slow down mod list loading" HorizontalAlignment="Left" />
<TextBlock Margin="5,0,5,5" Text="Requires application restart" HorizontalAlignment="Left" />
</StackPanel>
<TextBlock Grid.Row="6" Margin="5" Text="Enable OneClick Installs" FontWeight="Bold" HorizontalAlignment="Left" FontSize="16" />
<CheckBox Grid.Row="6" Grid.Column="1" Name="ProtocolHandler" VerticalAlignment="Center" HorizontalAlignment="Left" IsChecked="{Binding ProtocolHandlerEnabled, Mode=TwoWay}" Checked="ProtocolHandler_Checked" Unchecked="ProtocolHandler_Unchecked"/>
<StackPanel Grid.Row="7" Margin="20,0,0,0" Background="LightYellow" HorizontalAlignment="Left">
<TextBlock Margin="5,5,5,0" Text="Allows use of OneClick Install links" HorizontalAlignment="Left" />
<TextBlock Margin="5,0,5,5" Text="Requires Admin" HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Grid.Row="8" Margin="5" Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Text="Game Type: " FontWeight="Bold" FontSize="16" />
<TextBlock Text="{Binding InstallType}" FontSize="16"/>
</StackPanel>
</Grid>
</Page>

View file

@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Globalization;
namespace ModAssistant.Pages
{
/// <summary>
/// Interaction logic for Options.xaml
/// </summary>
///
public partial class Options : Page
{
public static Options Instance = new Options();
public string InstallDirectory { get; set; }
public string InstallType { get; set; }
public bool SaveSelection { get; set; }
public bool CheckInstalledMods { get; set; }
public Options()
{
InitializeComponent();
InstallDirectory = App.BeatSaberInstallDirectory;
InstallType = App.BeatSaberInstallType;
SaveSelection = App.SaveModSelection;
CheckInstalledMods = App.CheckInstalledMods;
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Utils.GetManualDir();
}
private void Test_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Utils.GetSteamDir());
}
private void SaveSelected_Checked(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.SaveSelected = true;
App.SaveModSelection = true;
Properties.Settings.Default.Save();
}
private void SaveSelected_Unchecked(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.SaveSelected = false;
App.SaveModSelection = false;
Properties.Settings.Default.Save();
}
private void CheckInstalled_Checked(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.CheckInstalled = true;
App.CheckInstalledMods = true;
CheckInstalledMods = true;
Properties.Settings.Default.Save();
}
private void CheckInstalled_Unchecked(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.CheckInstalled = false;
App.CheckInstalledMods = false;
CheckInstalledMods = false;
Properties.Settings.Default.Save();
}
private void ProtocolHandler_Checked(object sender, RoutedEventArgs e)
{
}
private void ProtocolHandler_Unchecked(object sender, RoutedEventArgs e)
{
}
}
}

View file

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ModAssistant")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ModAssistant")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModAssistant.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.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>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModAssistant.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View file

@ -0,0 +1,117 @@
<?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.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: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" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</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" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,98 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModAssistant.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")]
public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string InstallFolder {
get {
return ((string)(this["InstallFolder"]));
}
set {
this["InstallFolder"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string StoreType {
get {
return ((string)(this["StoreType"]));
}
set {
this["StoreType"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool SaveSelected {
get {
return ((bool)(this["SaveSelected"]));
}
set {
this["SaveSelected"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool CheckInstalled {
get {
return ((bool)(this["CheckInstalled"]));
}
set {
this["CheckInstalled"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public string SavedMods {
get {
return ((string)(this["SavedMods"]));
}
set {
this["SavedMods"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool Agreed {
get {
return ((bool)(this["Agreed"]));
}
set {
this["Agreed"] = value;
}
}
}
}

View file

@ -0,0 +1,24 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="ModAssistant.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="InstallFolder" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="StoreType" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="SaveSelected" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="CheckInstalled" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="SavedMods" Type="System.String" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="Agreed" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB