Commit ab7d3aa2 authored by Archnoc's avatar Archnoc

add launch options

parent 228ee37b
......@@ -14,16 +14,33 @@ namespace sunrise_launcher
public class ManifestMetadata
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("version")]
public string Version { get; set; }
[JsonPropertyName("launch_path")]
[JsonPropertyName("launch_options")]
public List<LaunchOption> LaunchOptions { get; set; }
public bool Verify()
{
if (LaunchOptions.Count == 0)
{
Console.WriteLine("need at least one launch config");
return false;
}
return LaunchOptions.All(x => x.Verify());
}
}
public class LaunchOption
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("path")]
public string LaunchPath { get; set; }
[JsonPropertyName("launch_env")]
public string LaunchEnv { get; set; }
[JsonPropertyName("launch_args")]
public string LaunchArgs { get; set; }
[JsonPropertyName("env")]
public string Env { get; set; }
[JsonPropertyName("args")]
public string Args { get; set; }
public bool Verify()
{
......
......@@ -4,23 +4,26 @@ namespace sunrise_launcher
{
public interface IManifestFactory
{
public IManifest Get(Server server);
public IManifest Get(string manifesturl);
}
public class ManifestFactory : IManifestFactory
{
const string manifiesta_v1 = "manifiesta-v1";
const string sunrise_api = "sunrise-api";
const string sunrise_json = "sunrise-json";
const string tequila_xml = "tequila-xml";
public IManifest Get(Server server)
public IManifest Get(string manifesturl)
{
var schema = getSchema(server.ManifestURL);
var schema = getSchema(manifesturl);
switch (schema)
{
case manifiesta_v1:
return new Manifiesta(server.ManifestURL);
case sunrise_api:
return new SunriseApi(manifesturl);
case sunrise_json:
return new SunriseJson(manifesturl);
case tequila_xml:
return new TequilaXML(server.ManifestURL);
return new TequilaXML(manifesturl);
}
return null;
}
......@@ -29,8 +32,10 @@ namespace sunrise_launcher
{
if (manifesturl.ToLower().EndsWith(".xml"))
return tequila_xml;
else if (manifesturl.ToLower().EndsWith(".json"))
return sunrise_json;
else
return manifiesta_v1;
return sunrise_api;
}
}
}
using Qml.Net;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace sunrise_launcher
{
public class Server : ManifestMetadata
public class Server
{
[JsonPropertyName("manifest_url")]
[NotifySignal("manifestUrlChanged")]
public string ManifestURL { get; set; }
[JsonPropertyName("install_path")]
public string InstallPath { get; set; }
[JsonPropertyName("metadata")]
public ManifestMetadata Metadata { get; set; }
[JsonPropertyName("launch")]
[NotifySignal("launchChanged")]
public string Launch { get; set; }
[JsonIgnore]
public State State { get; set; }
[JsonIgnore]
......
......@@ -68,7 +68,42 @@ namespace sunrise_launcher
file.Save(path);
}
public async Task AddAsync(string manifesturl, string installpath)
public async Task<ManifestMetadata> FindMetadataAsync(string manifesturl)
{
manifesturl = manifesturl.Trim();
try
{
var manifest = manifestFactory.Get(manifesturl);
if (manifest == null)
{
Console.WriteLine("Unknown manifest schema at '{0}'", manifesturl);
return null;
}
var metadata = await manifest.GetMetadataAsync();
if (metadata == null)
{
Console.WriteLine("Could not retrieve manifest from '{0}'", manifesturl);
return null;
}
if (!metadata.Verify())
{
Console.WriteLine("Manifest metadata failed inspection '{0}'", manifesturl);
return null;
}
return metadata;
}
catch (Exception ex)
{
Console.WriteLine("Exception in FindMetadataAsync: {0}", ex.Message);
return null;
}
}
public async Task AddAsync(string manifesturl, string installpath, string launch)
{
manifesturl = manifesturl.Trim();
if (Servers.Any(x => x.ManifestURL == manifesturl))
......@@ -80,11 +115,12 @@ namespace sunrise_launcher
var server = new Server();
server.ManifestURL = manifesturl;
server.InstallPath = CleanInstallPath(installpath);
server.Launch = launch;
await GetInfoAsync(server);
if (server.State == State.Error)
server.Metadata = await FindMetadataAsync(manifesturl);
if (server.Metadata == null)
{
ShowMessage(server.Error);
ShowMessage("Server add failed.");
return;
}
......@@ -97,15 +133,16 @@ namespace sunrise_launcher
ShowMessage(server.Error);
}
public async Task ConfigAsync(string oldmanifesturl, string manifesturl, string installpath)
public async Task ConfigAsync(string oldmanifesturl, string manifesturl, string installpath, string launch)
{
var server = Get(oldmanifesturl);
if (server == null) return;
server.ManifestURL = manifesturl.Trim();
server.InstallPath = CleanInstallPath(installpath);
server.Launch = launch;
await GetInfoAsync(server);
this.ActivateSignal("update");
//await GetInfoAsync(server);
//this.ActivateSignal("update");
await UpdateAsync(server, false);
this.ActivateSignal("update");
......@@ -161,7 +198,8 @@ namespace sunrise_launcher
ShowMessage(server.Error);
}
//this is called only when a new server is added
//this is called only when a new server is added or modified
/*
private async Task GetInfoAsync(Server server)
{
if (server.State == State.Updating)
......@@ -170,7 +208,7 @@ namespace sunrise_launcher
try
{
var manifest = manifestFactory.Get(server);
var manifest = manifestFactory.Get(server.ManifestURL);
if (manifest == null)
{
Console.WriteLine("Unknown manifest schema at '{0}'", server.ManifestURL);
......@@ -196,10 +234,16 @@ namespace sunrise_launcher
return;
}
server.Title = metadata.Title;
server.LaunchPath = metadata.LaunchPath;
server.LaunchEnv = metadata.LaunchEnv;
server.LaunchArgs = metadata.LaunchArgs;
server.Metadata = metadata;
if (metadata.LaunchOptions.Count == 0)
{
server.LaunchConfig = null;
}
else if (metadata.LaunchOptions.All(x => x.Title != server.LaunchConfig))
{
server.LaunchConfig = metadata.LaunchOptions[0].Title;
}
}
catch (Exception ex)
{
......@@ -208,7 +252,7 @@ namespace sunrise_launcher
server.Error = "Unknown Exception";
}
}
*/
private async Task UpdateAsync(Server server, bool force)
{
if (server.State == State.Updating)
......@@ -220,7 +264,7 @@ namespace sunrise_launcher
{
UpdateProgress(server, "Retrieving Manfiest", 0, 0);
var manifest = manifestFactory.Get(server);
var manifest = manifestFactory.Get(server.ManifestURL);
if (manifest == null)
{
Console.WriteLine("Unknown manifest schema at '{0}'", server.ManifestURL);
......@@ -246,7 +290,7 @@ namespace sunrise_launcher
return;
}
if (force || metadata.Version != server.Version)
if (force || metadata.Version != server.Metadata.Version)
{
await updatefiles(server, manifest, server.InstallPath);
}
......@@ -257,11 +301,13 @@ namespace sunrise_launcher
if (server.State == State.Ready)
{
server.Title = metadata.Title;
server.Version = metadata.Version;
server.LaunchPath = metadata.LaunchPath;
server.LaunchEnv = metadata.LaunchEnv;
server.LaunchArgs = metadata.LaunchArgs;
server.Metadata = metadata;
}
//if update occurs which removes the selected launch option, default to first option available
if (metadata.LaunchOptions.All(x => x.Title != server.Launch))
{
server.Launch = metadata.LaunchOptions[0].Title;
}
}
catch (Exception ex)
......@@ -436,12 +482,18 @@ namespace sunrise_launcher
try
{
var fullpath = Path.Combine(server.InstallPath, server.LaunchPath);
var launch = server.Metadata.LaunchOptions.FirstOrDefault(x => x.Title == server.Launch);
if (launch == null)
{
Console.WriteLine("ERROR: launch option not found: {0}", server.Launch);
}
var fullpath = Path.Combine(server.InstallPath, launch.LaunchPath);
var process = new Process();
process.StartInfo.WorkingDirectory = Path.GetDirectoryName(fullpath);
process.StartInfo.FileName = fullpath;
process.StartInfo.Arguments = server.LaunchArgs;
process.StartInfo.Arguments = launch.Args;
process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
process.Start();
}
......
......@@ -8,12 +8,12 @@ using System.Threading.Tasks;
namespace sunrise_launcher
{
public class Manifiesta : IManifest
public class SunriseApi : IManifest
{
private static HttpClient client = new HttpClient();
private string URL;
public Manifiesta(string url)
public SunriseApi(string url)
{
URL = url;
}
......
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace sunrise_launcher
{
public class SunriseJson : IManifest
{
private static HttpClient client = new HttpClient();
private string URL;
private Manifest Manifest;
public SunriseJson(string url)
{
URL = url;
}
private async Task FetchManifest()
{
if (Manifest != null)
return;
try
{
var response = await client.GetAsync(URL);
if (response.IsSuccessStatusCode)
{
using (var reader = await response.Content.ReadAsStreamAsync())
{
Manifest = await JsonSerializer.DeserializeAsync<Manifest>(reader);
}
}
}
catch (Exception ex)
{
Console.WriteLine("exception while retrieving manifest: {0}", ex.Message);
}
}
public async Task<ManifestMetadata> GetMetadataAsync()
{
try
{
await FetchManifest();
return Manifest;
}
catch (Exception ex)
{
Console.WriteLine("exception while retrieving manifest: {0}", ex.Message);
}
return null;
}
public async Task<IList<ManifestFile>> GetFilesAsync()
{
try
{
await FetchManifest();
if (Manifest == null)
return null;
return Manifest.Files;
}
catch (Exception ex)
{
Console.WriteLine("exception while retrieving manifest: {0}", ex.Message);
}
return null;
}
}
}
......@@ -54,14 +54,19 @@ namespace sunrise_launcher
if (TequilaRoot == null)
return null;
if (TequilaRoot.Profiles.Count == 0)
return null;
var metadata = new ManifestMetadata();
metadata.Version = Hash;
metadata.Title = TequilaRoot.Profiles[0].Value;
metadata.LaunchPath = TequilaRoot.Profiles[0].Exec;
metadata.LaunchArgs = TequilaRoot.Profiles[0].Params;
metadata.LaunchOptions = new List<LaunchOption>();
foreach (var profile in TequilaRoot.Profiles)
{
var config = new LaunchOption();
config.Title = profile.Value;
config.LaunchPath = profile.Exec;
config.Args = profile.Params;
metadata.LaunchOptions.Add(config);
}
return metadata;
}
......
......@@ -109,25 +109,93 @@ function configOpen(manifestURL) {
textfield_manifesturl.text = server.manifestURL;
textfield_installpath.text = server.installPath;
populateLaunchOptions(server.metadata);
combobox_launch.currentIndex = combobox_launch.find(server.launch);
dialog_config.manifestURL = manifestURL;
dialog_config.title = server.title;
dialog_config.visible = true;
}
function populateLaunchOptions(metadata) {
var options = [];
Net.listForEach(metadata.launchOptions, function (option) {
options.push(option.title);
});
combobox_launch.model = options;
}
function configUrlChanged() {
combobox_launch.currentIndex = -1;
combobox_launch.model = [];
}
function findUrl() {
combobox_launch.currentIndex = -1;
combobox_launch.model = [];
if (textfield_manifesturl.text === "") {
showInfo("Please enter a URL for the manifest.")
return;
}
var task = serverlist.findMetadataAsync(textfield_manifesturl.text);
Net.await(task, function (metadata) {
if (metadata == null) {
showMessage("Could not retrieve manifest at that location.")
return;
}
populateLaunchOptions(metadata);
combobox_launch.currentIndex = 0;
});
}
function configNew() {
textfield_manifesturl.text = "";
textfield_installpath.text = "";
dialog_config.manifestURL = "";
combobox_launch.currentIndex = -1;
combobox_launch.model = [];
dialog_config.title = "New Server";
dialog_config.visible = true;
}
function configSave() {
function configSave(action) {
if (action.button == StandardButton.Cancel)
return;
if (textfield_manifesturl.text === "") {
showInfo("Please enter a URL for the manifest.")
action.accepted = false;
return;
}
//auto "find" and select first launch option
if (combobox_launch.currentIndex == -1) {
var task = serverlist.findMetadataAsync(textfield_manifesturl.text);
Net.await(task, function (metadata) {
if (metadata == null) {
showMessage("Could not retrieve manifest at that location.")
return;
}
populateLaunchOptions(metadata);
combobox_launch.currentIndex = 0;
if (dialog_config.manifestURL === "") {
serverlist.addAsync(textfield_manifesturl.text, textfield_installpath.text, combobox_launch.currentText);
return;
}
serverlist.configAsync(dialog_config.manifestURL, textfield_manifesturl.text, textfield_installpath.text, combobox_launch.currentText);
});
return;
}
if (dialog_config.manifestURL === "") {
serverlist.addAsync(textfield_manifesturl.text, textfield_installpath.text);
serverlist.addAsync(textfield_manifesturl.text, textfield_installpath.text, combobox_launch.currentText);
return;
}
serverlist.configAsync(dialog_config.manifestURL, textfield_manifesturl.text, textfield_installpath.text);
serverlist.configAsync(dialog_config.manifestURL, textfield_manifesturl.text, textfield_installpath.text, combobox_launch.currentText);
}
function showError(error) {
......@@ -141,6 +209,11 @@ function showMessage(msg) {
dialogError.visible = true;
}
function showInfo(msg) {
dialogInfo.text = msg;
dialogInfo.visible = true;
}
function refreshProgress(manifestURL, taskName, taskDone, taskCount) {
if (serverlist.selected == null || taskName == "") {
paneProgress.visible = false;
......
......@@ -159,7 +159,7 @@ ApplicationWindow {
RadioButton {
id: button_server
y: 10
text: modelData.title
text: modelData.launch
ButtonGroup.group: buttongroup_servers
anchors.verticalCenter: parent.verticalCenter
anchors.left: button_remove.right
......@@ -384,8 +384,10 @@ ApplicationWindow {
standardButtons: StandardButton.Save | StandardButton.Cancel
modality: Qt.WindowModal
property string manifestURL
onAccepted: Main.configSave();
width: 500
property bool verified
onActionChosen: Main.configSave(action);
width: 548
height: 400
GridLayout {
......@@ -394,7 +396,22 @@ ApplicationWindow {
anchors.right: parent.right
anchors.rightMargin: 0
columns: 2
columns: 3
Text {
text: "Install Path"
font.family: fontMont.name
}
TextField {
placeholderText: "ex: servername or C:/CoH"
font.family: fontMont.name
id: textfield_installpath
Layout.fillWidth: true
selectByMouse: true
}
Text { text: " " }
Text {
text: "Manifest URL"
......@@ -406,19 +423,25 @@ ApplicationWindow {
id: textfield_manifesturl
Layout.fillWidth: true
selectByMouse: true
onTextChanged: Main.configUrlChanged()
}
Button {
text: "Find"
id: "button_findurl"
onClicked: Main.findUrl()
}
Text {
text: "Install Path"
text: "Launch"
font.family: fontMont.name
}
TextField {
placeholderText: "ex: servername or C:/CoH"
font.family: fontMont.name
id: textfield_installpath
ComboBox {
id: combobox_launch
Layout.fillWidth: true
selectByMouse: true
font.family: fontMont.name
palette.highlightedText: "black"
}
}
}
......@@ -441,6 +464,12 @@ ApplicationWindow {
informativeText: "See log.txt for details"
}
MessageDialog {
id: dialogInfo
modality: Qt.WindowModal
standardButtons: StandardButton.Ok
}
Component.onCompleted: Main.init()
onClosing: serverlist.save("./servers.json");
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PublishTrimmed>true</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment