220 lines
9.0 KiB
C#
220 lines
9.0 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Reactive;
|
|
using System.Reactive.Linq;
|
|
using System.Text;
|
|
using System.Text.Json.Nodes;
|
|
using Avalonia.Media;
|
|
using MiNET.LevelDB;
|
|
using ReactiveUI;
|
|
|
|
namespace VaultSmpInstaller.ViewModels;
|
|
|
|
public class ProfileWindow1ViewModel : ViewModelBase
|
|
{
|
|
public Interaction<ProfileWindow2ViewModel, ProfileWindow2ViewModel.InstanceInfo?> ShowProfileSelectionDialog { get; }
|
|
|
|
public ReactiveCommand<Unit, ProfileWindow2ViewModel.InstanceInfo?> UseCurseforgeCommand { get; }
|
|
public ReactiveCommand<Unit, ProfileWindow2ViewModel.InstanceInfo?> UsePrismCommand { get; }
|
|
public ReactiveCommand<Unit, ProfileWindow2ViewModel.InstanceInfo?> UseOverwolfCommand { get; }
|
|
|
|
public ProfileWindow1ViewModel()
|
|
{
|
|
var curseforgeDir = CurseforgeInstanceDir;
|
|
var prismDir = PrismInstanceDir;
|
|
var overwolfDir = OverwolfInstanceDir;
|
|
|
|
ShowProfileSelectionDialog = new Interaction<ProfileWindow2ViewModel, ProfileWindow2ViewModel.InstanceInfo?>();
|
|
|
|
UseCurseforgeCommand = ReactiveCommand.CreateFromTask(async () =>
|
|
{
|
|
var profileWindowModel = new ProfileWindow2ViewModel(ProfileWindow2ViewModel.InstanceType.Curseforge, curseforgeDir);
|
|
return await ShowProfileSelectionDialog.Handle(profileWindowModel);
|
|
});
|
|
|
|
UsePrismCommand = ReactiveCommand.CreateFromTask(async () =>
|
|
{
|
|
var profileWindowModel = new ProfileWindow2ViewModel(ProfileWindow2ViewModel.InstanceType.Prism, prismDir);
|
|
return await ShowProfileSelectionDialog.Handle(profileWindowModel);
|
|
});
|
|
|
|
UseOverwolfCommand = ReactiveCommand.CreateFromTask(async () =>
|
|
{
|
|
var profileWindowModel = new ProfileWindow2ViewModel(ProfileWindow2ViewModel.InstanceType.Overwolf, overwolfDir);
|
|
return await ShowProfileSelectionDialog.Handle(profileWindowModel);
|
|
});
|
|
|
|
}
|
|
|
|
public static Brush Background => SolidColorBrush.Parse("#282A36");
|
|
public static Brush SecondaryBackground => SolidColorBrush.Parse("#44475A");
|
|
public static Brush ButtonBackground => SolidColorBrush.Parse("#6272A4");
|
|
public static Brush TextColor => SolidColorBrush.Parse("#F8F8F2");
|
|
|
|
private string? _curseforgeInstanceDir = null;
|
|
public bool IsCurseforgeInstalled { get; set; } = false;
|
|
|
|
public string CurseforgeButtonText => IsCurseforgeInstalled ? "Curseforge" : "Curseforge Not Detected";
|
|
|
|
public string? CurseforgeInstanceDir
|
|
{
|
|
get
|
|
{
|
|
if (_curseforgeInstanceDir == null && TryGetCurseforgeMinecraftRoot(out _curseforgeInstanceDir))
|
|
{
|
|
IsCurseforgeInstalled = true;
|
|
this.RaisePropertyChanged(nameof(IsCurseforgeInstalled));
|
|
this.RaisePropertyChanged(nameof(CurseforgeButtonText));
|
|
this.RaisePropertyChanged();
|
|
}
|
|
return _curseforgeInstanceDir;
|
|
}
|
|
}
|
|
|
|
public bool IsPrismInstalled { get; set; } = false;
|
|
|
|
private string? _prismInstanceDir = null;
|
|
public string PrismButtonText => IsPrismInstalled ? "Prism Launcher" : "Prism Launcher Not Detected";
|
|
|
|
public string? PrismInstanceDir
|
|
{
|
|
get
|
|
{
|
|
if (_prismInstanceDir == null && TryGetPrismMinecraftRoot(out _prismInstanceDir))
|
|
{
|
|
IsPrismInstalled = true;
|
|
this.RaisePropertyChanged(nameof(IsPrismInstalled));
|
|
this.RaisePropertyChanged(nameof(PrismButtonText));
|
|
this.RaisePropertyChanged();
|
|
}
|
|
return _prismInstanceDir;
|
|
}
|
|
}
|
|
|
|
public bool IsOverwolfInstalled { get; set; } = false;
|
|
|
|
private string? _overwolfInstanceDir = null;
|
|
public string OverwolfButtonText => IsOverwolfInstalled ? "Curseforge (Overwolf)" : "Curseforge (Overwolf) Not Detected";
|
|
|
|
public string? OverwolfInstanceDir
|
|
{
|
|
get
|
|
{
|
|
if (_overwolfInstanceDir == null && TryGetOverwolfMinecraftRoot(out _overwolfInstanceDir))
|
|
{
|
|
IsOverwolfInstalled = true;
|
|
this.RaisePropertyChanged(nameof(IsOverwolfInstalled));
|
|
this.RaisePropertyChanged(nameof(OverwolfButtonText));
|
|
this.RaisePropertyChanged();
|
|
}
|
|
return _overwolfInstanceDir;
|
|
}
|
|
}
|
|
|
|
public bool TryGetCurseforgeMinecraftRoot(out string? minecraftRoot)
|
|
{
|
|
minecraftRoot = null;
|
|
|
|
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
|
|
|
if (!File.Exists(Path.Combine(appData, "Curseforge", "storage.json"))) return false;
|
|
|
|
var curseforgeConfig = JsonNode.Parse(File.ReadAllText(Path.Combine(appData, "Curseforge", "storage.json")))!.AsObject();
|
|
if (!curseforgeConfig.TryGetPropertyValue("minecraft-settings", out var minecraftSettingsNode))
|
|
{
|
|
minecraftRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "curseforge", "minecraft", "Instances");
|
|
return true;
|
|
}
|
|
if (!minecraftSettingsNode!.AsValue().TryGetValue(out string? minecraftSettingsString)) return false;
|
|
|
|
var minecraftSettings = JsonNode.Parse(minecraftSettingsString);
|
|
if (!minecraftSettings!.AsObject().TryGetPropertyValue("minecraftRoot", out var minecraftRootNode)) {
|
|
minecraftRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "curseforge", "minecraft", "Instances");
|
|
return true;
|
|
}
|
|
if (!minecraftRootNode!.AsValue().TryGetValue(out minecraftRoot)) return false;
|
|
|
|
minecraftRoot = Path.Combine(minecraftRoot, "Instances");
|
|
return true;
|
|
}
|
|
|
|
public bool TryGetPrismMinecraftRoot(out string? minecraftRoot)
|
|
{
|
|
minecraftRoot = null;
|
|
|
|
var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
|
|
|
if (!File.Exists(Path.Combine(appData, "PrismLauncher", "prismlauncher.cfg"))) return false;
|
|
|
|
foreach(String line in File.ReadLines(Path.Combine(appData, "PrismLauncher", "prismlauncher.cfg")))
|
|
{
|
|
if (line.StartsWith("InstanceDir"))
|
|
{
|
|
string path = line.Split('=', 2)[1];
|
|
if (Path.IsPathFullyQualified(path))
|
|
minecraftRoot = path;
|
|
else
|
|
minecraftRoot = Path.Combine(appData, "PrismLauncher", path);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool TryGetOverwolfMinecraftRoot(out string? minecraftRoot)
|
|
{
|
|
minecraftRoot = null;
|
|
|
|
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
|
var overwolfDbDirectory = Path.Combine(localAppData, "Overwolf", "BrowserCache", "Local Storage", "leveldb");
|
|
|
|
if (!Directory.Exists(overwolfDbDirectory)) return false;
|
|
|
|
var overwolfDb = new Database(new(overwolfDbDirectory), false, new Options() { ReadOnly = true });
|
|
byte[] databaseKey = new byte[]
|
|
{
|
|
0x5F, 0x6F,
|
|
0x76, 0x65, 0x72, 0x77, 0x6F, 0x6C, 0x66, 0x2D,
|
|
0x65, 0x78, 0x74, 0x65, 0x6E, 0x73, 0x69, 0x6F,
|
|
0x6E, 0x3A, 0x2F, 0x2F, 0x63, 0x63, 0x68, 0x68,
|
|
0x63, 0x61, 0x69, 0x61, 0x70, 0x65, 0x69, 0x6B,
|
|
0x6A, 0x62, 0x64, 0x62, 0x70, 0x66, 0x70, 0x6C,
|
|
0x67, 0x6D, 0x70, 0x6F, 0x62, 0x62, 0x63, 0x64,
|
|
0x6B, 0x64, 0x61, 0x70, 0x68, 0x63, 0x6C, 0x62,
|
|
0x6D, 0x6B, 0x62, 0x6A, 0x00, 0x01, 0x6D, 0x69,
|
|
0x6E, 0x65, 0x63, 0x72, 0x61, 0x66, 0x74, 0x2D,
|
|
0x73, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x73
|
|
};
|
|
String? curseforgeMinecraftSettings = "";
|
|
try
|
|
{
|
|
overwolfDb.Open();
|
|
curseforgeMinecraftSettings = Encoding.ASCII.GetString(overwolfDb.Get(databaseKey))[1..];
|
|
}
|
|
catch (NullReferenceException e)
|
|
{
|
|
minecraftRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "curseforge", "minecraft", "Instances");
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
overwolfDb.Close();
|
|
overwolfDb.Dispose();
|
|
}
|
|
if(String.IsNullOrEmpty(curseforgeMinecraftSettings))
|
|
{
|
|
minecraftRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "curseforge", "minecraft", "Instances");
|
|
return true;
|
|
}
|
|
|
|
var minecraftSettings = JsonNode.Parse(curseforgeMinecraftSettings);
|
|
if (!minecraftSettings!.AsObject().TryGetPropertyValue("minecraftRoot", out var minecraftRootNode)) {
|
|
minecraftRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "curseforge", "minecraft", "Instances");
|
|
return true;
|
|
}
|
|
if (!minecraftRootNode!.AsValue().TryGetValue(out minecraftRoot)) return false;
|
|
|
|
minecraftRoot = Path.Combine(minecraftRoot, "Instances");
|
|
return true;
|
|
}
|
|
} |