diff --git a/BeatSaber-Versions.csproj b/BeatSaber-Versions.csproj
new file mode 100644
index 0000000..f5135ed
--- /dev/null
+++ b/BeatSaber-Versions.csproj
@@ -0,0 +1,16 @@
+
+
+
+ WinExe
+ net6.0-windows
+ BeatSaber_Versions
+ enable
+ true
+ enable
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BeatSaber-Versions.sln b/BeatSaber-Versions.sln
new file mode 100644
index 0000000..60e13f4
--- /dev/null
+++ b/BeatSaber-Versions.sln
@@ -0,0 +1,30 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.32112.339
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeatSaber-Versions", "BeatSaber-Versions.csproj", "{92403BEE-848E-4C1D-9629-AE45CFE516C6}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D699286A-E227-419D-B679-C06476A92A01}"
+ ProjectSection(SolutionItems) = preProject
+ config.yaml = config.yaml
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {92403BEE-848E-4C1D-9629-AE45CFE516C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {92403BEE-848E-4C1D-9629-AE45CFE516C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {92403BEE-848E-4C1D-9629-AE45CFE516C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {92403BEE-848E-4C1D-9629-AE45CFE516C6}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {FB96C177-79F2-4B97-8A56-26C1763D0B30}
+ EndGlobalSection
+EndGlobal
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..37cce0e
--- /dev/null
+++ b/Program.cs
@@ -0,0 +1,17 @@
+namespace BeatSaber_Versions
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new VersionChanger());
+ }
+ }
+}
\ No newline at end of file
diff --git a/VersionChanger.Designer.cs b/VersionChanger.Designer.cs
new file mode 100644
index 0000000..01bcf4f
--- /dev/null
+++ b/VersionChanger.Designer.cs
@@ -0,0 +1,237 @@
+namespace BeatSaber_Versions
+{
+ partial class VersionChanger
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.playSelected = new System.Windows.Forms.Button();
+ this.versionListBox = new System.Windows.Forms.ListBox();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.folderPath = new System.Windows.Forms.TextBox();
+ this.versionVersion = new System.Windows.Forms.TextBox();
+ this.setFolder = new System.Windows.Forms.Button();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.selectFolderForVersion = new System.Windows.Forms.FolderBrowserDialog();
+ this.button2 = new System.Windows.Forms.Button();
+ this.versionName = new System.Windows.Forms.TextBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this.saveSetting = new System.Windows.Forms.Button();
+ this.menuStrip1.SuspendLayout();
+ this.panel1.SuspendLayout();
+ this.groupBox1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.toolStripMenuItem1});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Size = new System.Drawing.Size(1008, 24);
+ this.menuStrip1.TabIndex = 0;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // toolStripMenuItem1
+ //
+ this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+ this.toolStripMenuItem1.Size = new System.Drawing.Size(125, 20);
+ this.toolStripMenuItem1.Text = "toolStripMenuItem1";
+ //
+ // panel1
+ //
+ this.panel1.Controls.Add(this.button2);
+ this.panel1.Controls.Add(this.playSelected);
+ this.panel1.Location = new System.Drawing.Point(0, 27);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(1008, 36);
+ this.panel1.TabIndex = 1;
+ //
+ // playSelected
+ //
+ this.playSelected.Location = new System.Drawing.Point(908, 10);
+ this.playSelected.Name = "playSelected";
+ this.playSelected.Size = new System.Drawing.Size(96, 23);
+ this.playSelected.TabIndex = 3;
+ this.playSelected.Text = "Play Selected";
+ this.playSelected.UseVisualStyleBackColor = true;
+ this.playSelected.Click += new System.EventHandler(this.playSelected_Click);
+ //
+ // versionListBox
+ //
+ this.versionListBox.FormattingEnabled = true;
+ this.versionListBox.ItemHeight = 15;
+ this.versionListBox.Location = new System.Drawing.Point(2, 66);
+ this.versionListBox.Name = "versionListBox";
+ this.versionListBox.Size = new System.Drawing.Size(164, 454);
+ this.versionListBox.TabIndex = 2;
+ this.versionListBox.SelectedIndexChanged += new System.EventHandler(this.versionListBox_SelectedIndexChanged);
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.saveSetting);
+ this.groupBox1.Controls.Add(this.label3);
+ this.groupBox1.Controls.Add(this.versionName);
+ this.groupBox1.Controls.Add(this.folderPath);
+ this.groupBox1.Controls.Add(this.versionVersion);
+ this.groupBox1.Controls.Add(this.setFolder);
+ this.groupBox1.Controls.Add(this.label2);
+ this.groupBox1.Controls.Add(this.label1);
+ this.groupBox1.Location = new System.Drawing.Point(167, 66);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(838, 454);
+ this.groupBox1.TabIndex = 3;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "groupBox1";
+ //
+ // folderPath
+ //
+ this.folderPath.Location = new System.Drawing.Point(132, 79);
+ this.folderPath.Name = "folderPath";
+ this.folderPath.Size = new System.Drawing.Size(603, 23);
+ this.folderPath.TabIndex = 4;
+ //
+ // versionVersion
+ //
+ this.versionVersion.Location = new System.Drawing.Point(132, 51);
+ this.versionVersion.Name = "versionVersion";
+ this.versionVersion.Size = new System.Drawing.Size(603, 23);
+ this.versionVersion.TabIndex = 3;
+ //
+ // setFolder
+ //
+ this.setFolder.Location = new System.Drawing.Point(741, 79);
+ this.setFolder.Name = "setFolder";
+ this.setFolder.Size = new System.Drawing.Size(75, 23);
+ this.setFolder.TabIndex = 2;
+ this.setFolder.Text = "Set Folder";
+ this.setFolder.UseVisualStyleBackColor = true;
+ this.setFolder.Click += new System.EventHandler(this.setFolder_Click);
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(18, 82);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(40, 15);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "Folder";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(18, 54);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(45, 15);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "Version";
+ //
+ // selectFolderForVersion
+ //
+ this.selectFolderForVersion.HelpRequest += new System.EventHandler(this.folderBrowserDialog1_HelpRequest);
+ //
+ // button2
+ //
+ this.button2.Location = new System.Drawing.Point(3, 10);
+ this.button2.Name = "button2";
+ this.button2.Size = new System.Drawing.Size(87, 23);
+ this.button2.TabIndex = 4;
+ this.button2.Text = "Add Version";
+ this.button2.UseVisualStyleBackColor = true;
+ //
+ // versionName
+ //
+ this.versionName.Location = new System.Drawing.Point(132, 22);
+ this.versionName.Name = "versionName";
+ this.versionName.Size = new System.Drawing.Size(603, 23);
+ this.versionName.TabIndex = 5;
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(18, 25);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(39, 15);
+ this.label3.TabIndex = 6;
+ this.label3.Text = "Name";
+ //
+ // saveSetting
+ //
+ this.saveSetting.Location = new System.Drawing.Point(741, 108);
+ this.saveSetting.Name = "saveSetting";
+ this.saveSetting.Size = new System.Drawing.Size(75, 23);
+ this.saveSetting.TabIndex = 7;
+ this.saveSetting.Text = "Save";
+ this.saveSetting.UseVisualStyleBackColor = true;
+ this.saveSetting.Click += new System.EventHandler(this.saveSetting_Click);
+ //
+ // VersionChanger
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1008, 525);
+ this.Controls.Add(this.groupBox1);
+ this.Controls.Add(this.versionListBox);
+ this.Controls.Add(this.panel1);
+ this.Controls.Add(this.menuStrip1);
+ this.MainMenuStrip = this.menuStrip1;
+ this.Name = "VersionChanger";
+ this.Text = "Form1";
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.panel1.ResumeLayout(false);
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private MenuStrip menuStrip1;
+ private ToolStripMenuItem toolStripMenuItem1;
+ private Panel panel1;
+ private Button playSelected;
+ private ListBox gameVersions;
+ private ListBox versionListBox;
+ private GroupBox groupBox1;
+ private TextBox folderPath;
+ private TextBox versionVersion;
+ private Button setFolder;
+ private Label label2;
+ private Label label1;
+ private FolderBrowserDialog selectFolderForVersion;
+ private Button button2;
+ private Label label3;
+ private TextBox versionName;
+ private Button saveSetting;
+ }
+}
\ No newline at end of file
diff --git a/VersionChanger.cs b/VersionChanger.cs
new file mode 100644
index 0000000..e3a2001
--- /dev/null
+++ b/VersionChanger.cs
@@ -0,0 +1,158 @@
+using BeatSaber_Versions.controller;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using YamlDotNet.Serialization;
+using YamlDotNet.Serialization.NamingConventions;
+
+namespace BeatSaber_Versions
+{
+ public partial class VersionChanger : Form
+ {
+ [DllImport("kernel32.dll")]
+ static extern bool CreateSymbolicLink(string lpSymlinkFileName,
+ string lpTargetFileName, int dwFlags);
+
+ private string Path = $@"{AppDomain.CurrentDomain.BaseDirectory}config.yaml";
+ private VersionConfigDict Versionen = null;
+ private String beatsaberfolder = @"A:\BS";
+
+ public VersionChanger()
+ {
+
+ InitializeComponent();
+
+ var deserializer = new DeserializerBuilder()
+ .WithNamingConvention(UnderscoredNamingConvention.Instance) // see height_in_inches in sample yml
+ .Build();
+
+ string yml = File.ReadAllText(Path);
+ var p = deserializer.Deserialize(yml);
+
+ Versionen = p;
+ beatsaberfolder = p.beatsaberfolder;
+ foreach (var key in (p.versions).Keys)
+ {
+ versionListBox.Items.Add(key);
+ }
+
+
+ }
+
+ private void folderBrowserDialog1_HelpRequest(object sender, EventArgs e)
+ {
+
+ }
+
+ private void setFolder_Click(object sender, EventArgs e)
+ {
+ DialogResult folder = selectFolderForVersion.ShowDialog();
+ if(folder == DialogResult.OK)
+ {
+ MessageBox.Show("" + selectFolderForVersion.SelectedPath);
+ folderPath.Text = selectFolderForVersion.SelectedPath;
+
+
+ }
+ else
+ {
+
+ }
+
+ }
+ private void versionListBox_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ var Item = ((sender as ListBox).SelectedItem);
+ if(Item != null)
+ {
+ folderPath.Text = Versionen.versions[(String)Item].path;
+ versionName.Text = Versionen.versions[(String)Item].name;
+ versionVersion.Text = Versionen.versions[(String)Item].version;
+ }
+ }
+
+ private void playSelected_Click(object sender, EventArgs e)
+ {
+ String Target = folderPath.Text;
+ if (Directory.Exists(beatsaberfolder))
+ {
+ if (IsSymbolic(beatsaberfolder))
+ {
+ Directory.Delete(beatsaberfolder);
+ if (Directory.Exists(Target))
+ {
+ CreateSymbolicLink(beatsaberfolder, Target, 0x1);
+ setSongFolder();
+ }
+ }
+ }
+ else
+ {
+ if (Directory.Exists(Target))
+ {
+ CreateSymbolicLink(beatsaberfolder, Target, 0x1);
+ setSongFolder();
+ }
+ }
+ }
+ private void setSongFolder()
+ {
+ String songFolderConf = Versionen.beatsabersongs;
+ String songFolder = beatsaberfolder+ "\\Beat Saber_Data\\CustomLevels";
+ if (Directory.Exists(songFolder))
+ {
+ if (IsSymbolic(songFolder))
+ {
+ MessageBox.Show("Is a symbolic link <3");
+ }
+ else
+ {
+ MessageBox.Show("Is a normal folder.");
+ }
+ }
+ else
+ {
+ DialogResult dialogResult = MessageBox.Show("Create symbolic link, may deduplicate your song library", "Settings", MessageBoxButtons.YesNo);
+ if (dialogResult == DialogResult.Yes)
+ {
+ CreateSymbolicLink(songFolder, songFolderConf, 0x1);
+ MessageBox.Show("Created symbolic link to song folder.");
+ }
+ else if (dialogResult == DialogResult.No)
+ {
+ //do something else
+ }
+
+ }
+
+
+ }
+
+
+ private void saveSetting_Click(object sender, EventArgs e)
+ {
+ VersionConfig tmp = new VersionConfig();
+ tmp.path = folderPath.Text;
+ tmp.name = versionName.Text;
+ tmp.version = versionVersion.Text;
+ if (Versionen.versions.ContainsKey((String)tmp.version))
+ {
+
+ }
+ else
+ {
+
+ }
+ }
+
+
+ /**
+ * Helper
+ */
+ private bool IsSymbolic(string path)
+ {
+ FileInfo pathInfo = new FileInfo(path);
+ return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint);
+ }
+ }
+}
\ No newline at end of file
diff --git a/VersionChanger.resx b/VersionChanger.resx
new file mode 100644
index 0000000..6bc442a
--- /dev/null
+++ b/VersionChanger.resx
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 132, 17
+
+
+ 119
+
+
\ No newline at end of file
diff --git a/config.yaml b/config.yaml
new file mode 100644
index 0000000..5689522
--- /dev/null
+++ b/config.yaml
@@ -0,0 +1,14 @@
+beatsaberfolder: C:\\Program Files (x86)\\Steam\\steamapps\\common\\BeatSaber
+versions:
+ 1.18.3:
+ version: 1.18.3
+ path: D:\\Games\\BeatSaber Online
+ name: Multiplayer
+ 1.21.0:
+ version: 1.21.0
+ path: C:\\Program Files (x86)\\Steam\\steamapps\\common\\Beat Saber-Stream
+ name: Stream
+ 1.22.0:
+ version: 1.22.0
+ path: C:\\Program Files (x86)\\Steam\\steamapps\\common\\Beat Saber-new
+ name: Stream
\ No newline at end of file
diff --git a/controller/VersionConfig.cs b/controller/VersionConfig.cs
new file mode 100644
index 0000000..91fec8a
--- /dev/null
+++ b/controller/VersionConfig.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BeatSaber_Versions.controller
+{
+ internal class VersionConfig
+
+ {
+ public string version { get; set; }
+ public string name { get; set; }
+ public string path { get; set; }
+ }
+}
diff --git a/controller/VersionConfigDict.cs b/controller/VersionConfigDict.cs
new file mode 100644
index 0000000..a699498
--- /dev/null
+++ b/controller/VersionConfigDict.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BeatSaber_Versions.controller
+{
+ internal class VersionConfigDict
+ {
+ public String? beatsabersongs { get; set; }
+ public String? beatsaberfolder { get; set; }
+ public Dictionary versions { get; set; }
+ }
+}