Added game manifest model. Reworked settings to be a bit more universal across the extension. Made server URL configurable.

dashboard
Pat Hartl 2023-01-07 12:34:12 -06:00
parent cf326dd5ca
commit 787a983c03
10 changed files with 188 additions and 55 deletions

View File

@ -82,6 +82,9 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
<Reference Include="YamlDotNet, Version=12.0.0.0, Culture=neutral, PublicKeyToken=ec19458f3c15af5e, processorArchitecture=MSIL">
<HintPath>..\packages\YamlDotNet.12.3.1\lib\net45\YamlDotNet.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="InstallController.cs" />

View File

@ -14,12 +14,12 @@ namespace LANCommander.Playnite.Extension
{
internal class LANCommanderClient
{
private readonly RestClient Client;
public readonly RestClient Client;
public AuthToken Token;
public LANCommanderClient()
public LANCommanderClient(string baseUrl)
{
Client = new RestClient("https://localhost:7087");
Client = new RestClient(baseUrl);
}
private T PostRequest<T>(string route, object body)
@ -89,6 +89,9 @@ namespace LANCommander.Playnite.Extension
var response = Client.Post<AuthResponse>(request);
if (response.StatusCode != HttpStatusCode.OK)
throw new WebException(response.ErrorMessage);
return response.Data;
}

View File

@ -1,19 +1,24 @@
using Playnite.SDK;
using LANCommander.Models;
using Playnite.SDK;
using Playnite.SDK.Models;
using Playnite.SDK.Plugins;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using PN = Playnite;
namespace LANCommander.Playnite.Extension
{
public class PlayniteLibraryPlugin : LibraryPlugin
{
public static readonly ILogger Logger = LogManager.GetLogger();
private PlayniteSettingsViewModel Settings { get; set; }
internal PlayniteSettingsViewModel Settings { get; set; }
internal LANCommanderClient LANCommander { get; set; }
public override Guid Id { get; } = Guid.Parse("48e1bac7-e0a0-45d7-ba83-36f5e9e959fc");
@ -22,41 +27,19 @@ namespace LANCommander.Playnite.Extension
public PlayniteLibraryPlugin(IPlayniteAPI api) : base(api)
{
LANCommander = new LANCommanderClient();
Settings = new PlayniteSettingsViewModel(this);
Properties = new LibraryPluginProperties
{
HasSettings = true,
};
LoadSettings();
}
public override IEnumerable<GameMetadata> GetGames(LibraryGetGamesArgs args)
{
try
{
var token = new SDK.Models.AuthToken()
{
AccessToken = Settings.AccessToken,
RefreshToken = Settings.RefreshToken,
};
LANCommander.Token = token;
var tokenIsValid = LANCommander.ValidateToken(token);
if (!tokenIsValid)
{
try
{
LANCommander.RefreshToken(token);
}
catch
{
ShowAuthenticationWindow();
}
}
LANCommander.Token = token;
var syncedGames = PlayniteApi.Database.Games;
var games = LANCommander
.GetGames()
@ -101,6 +84,52 @@ namespace LANCommander.Playnite.Extension
return new PlayniteSettingsView(this);
}
public void LoadSettings()
{
Settings = LoadPluginSettings<PlayniteSettingsViewModel>();
try
{
if (LANCommander == null)
LANCommander = new LANCommanderClient(Settings.ServerAddress);
LANCommander.Client.BaseUrl = new Uri(Settings.ServerAddress);
var token = new SDK.Models.AuthToken()
{
AccessToken = Settings.AccessToken,
RefreshToken = Settings.RefreshToken,
};
LANCommander.Token = token;
}
catch
{
}
}
public void SaveSettings()
{
SavePluginSettings(Settings);
if (LANCommander == null)
LANCommander = new LANCommanderClient(Settings.ServerAddress);
if (Settings.ServerAddress != LANCommander.Client.BaseUrl.ToString())
{
LANCommander.Client.BaseUrl = new Uri(Settings.ServerAddress);
var token = new SDK.Models.AuthToken()
{
AccessToken = Settings.AccessToken,
RefreshToken = Settings.RefreshToken,
};
LANCommander.Token = token;
}
}
public System.Windows.Window ShowAuthenticationWindow()
{
var window = PlayniteApi.Dialogs.CreateWindow(new WindowCreationOptions()
@ -119,5 +148,44 @@ namespace LANCommander.Playnite.Extension
return window;
}
private GameMetadata ParseManifest(string installDirectory)
{
var manifestContents = File.ReadAllText(Path.Combine(installDirectory, "_manifest.yml"));
var deserializer = new DeserializerBuilder()
.WithNamingConvention(PascalCaseNamingConvention.Instance)
.Build();
try
{
var manifest = deserializer.Deserialize<GameManifest>(manifestContents);
var metadata = new GameMetadata()
{
Name = manifest.Title,
SortingName = manifest.SortTitle,
Description = manifest.Description,
ReleaseDate = new ReleaseDate(manifest.ReleasedOn),
Version = manifest.Version,
GameActions = manifest.Actions.Select(a =>
{
return new PN.SDK.Models.GameAction()
{
Name = a.Name,
Arguments = a.Arguments,
Path = a.Path,
WorkingDir = a.WorkingDirectory,
IsPlayAction = a.IsPrimaryAction
};
}).ToList()
};
return metadata;
}
catch
{
throw new FileNotFoundException("The manifest file is invalid or corrupt.");
}
}
}
}

View File

@ -12,7 +12,7 @@ namespace LANCommander.Playnite.Extension
{
private readonly PlayniteLibraryPlugin Plugin;
public string ServerUrl { get; set; } = String.Empty;
public string ServerAddress { get; set; } = String.Empty;
public string AccessToken { get; set; } = String.Empty;
public string RefreshToken { get; set; } = String.Empty;
@ -25,14 +25,9 @@ namespace LANCommander.Playnite.Extension
{
Plugin = plugin;
var savedSettings = Plugin.LoadPluginSettings<PlayniteSettingsViewModel>();
if (savedSettings != null)
{
ServerUrl = savedSettings.ServerUrl;
AccessToken = savedSettings.AccessToken;
RefreshToken = savedSettings.RefreshToken;
}
ServerAddress = Plugin.Settings.ServerAddress;
AccessToken = Plugin.Settings.AccessToken;
RefreshToken = Plugin.Settings.RefreshToken;
}
public void BeginEdit()
@ -47,7 +42,9 @@ namespace LANCommander.Playnite.Extension
public void EndEdit()
{
// Plugin.SavePluginSettings(this);
Plugin.Settings.ServerAddress = ServerAddress;
Plugin.SaveSettings();
}
public bool VerifySettings(out List<string> errors)

View File

@ -27,12 +27,17 @@ namespace LANCommander.Playnite.Extension
InitializeComponent();
var settings = new PlayniteSettingsViewModel(plugin);
UpdateAuthenticationButtonVisibility();
}
private void UpdateAuthenticationButtonVisibility()
{
try
{
if (Plugin.LANCommander.ValidateToken(new AuthToken()
{
AccessToken = settings.AccessToken,
RefreshToken = settings.RefreshToken,
AccessToken = Plugin.Settings.AccessToken,
RefreshToken = Plugin.Settings.RefreshToken,
}))
{
var authenticateButton = FindName("AuthenticateButton") as Button;
@ -40,10 +45,22 @@ namespace LANCommander.Playnite.Extension
authenticateButton.Visibility = Visibility.Hidden;
}
}
catch
{
}
}
private void AuthenticateButton_Click(object sender, RoutedEventArgs e)
{
Plugin.ShowAuthenticationWindow();
var authWindow = Plugin.ShowAuthenticationWindow();
authWindow.Closed += AuthWindow_Closed;
}
private void AuthWindow_Closed(object sender, EventArgs e)
{
UpdateAuthenticationButtonVisibility();
}
}
}

View File

@ -8,6 +8,7 @@ namespace LANCommander.Playnite.Extension.ViewModels
{
internal class Authentication
{
public string ServerAddress { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}

View File

@ -13,6 +13,8 @@
</Style>
</d:DesignerProperties.DesignStyle>
<StackPanel Margin="20">
<TextBlock Text="Server Address" />
<TextBox Name="ServerAddress" Text="{Binding ServerAddress}" KeyDown="TextBox_KeyDown" />
<TextBlock Text="Username"/>
<TextBox Name="Username" Text="{Binding UserName}" KeyDown="TextBox_KeyDown" />
<TextBlock Text="Password" />

View File

@ -21,12 +21,10 @@ namespace LANCommander.Playnite.Extension.Views
{
private PlayniteLibraryPlugin Plugin;
private ViewModels.Authentication Context { get { return (ViewModels.Authentication)DataContext; } }
private PlayniteSettingsViewModel Settings { get; set; }
public Authentication(PlayniteLibraryPlugin plugin)
{
Plugin = plugin;
Settings = Plugin.GetSettings(false) as PlayniteSettingsViewModel;
InitializeComponent();
}
@ -56,16 +54,21 @@ namespace LANCommander.Playnite.Extension.Views
{
try
{
if (Plugin.LANCommander == null)
Plugin.LANCommander = new LANCommanderClient(Context.ServerAddress);
else
Plugin.LANCommander.Client.BaseUrl = new Uri(Context.ServerAddress);
var response = Plugin.LANCommander.Authenticate(Context.UserName, Context.Password);
Settings.AccessToken = response.AccessToken;
Settings.RefreshToken = response.RefreshToken;
Plugin.Settings.ServerAddress = Context.ServerAddress;
Plugin.Settings.AccessToken = response.AccessToken;
Plugin.Settings.RefreshToken = response.RefreshToken;
// Probably unneeded, but why not be more secure?
Context.Password = String.Empty;
Plugin.SavePluginSettings(Settings);
//Plugin.Settings = Plugin.LoadPluginSettings<PlayniteSettingsViewModel>();
Plugin.SaveSettings();
Window.GetWindow(this).Close();
}

View File

@ -12,4 +12,5 @@
<package id="System.Text.Json" version="5.0.1" targetFramework="net462" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net462" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net462" />
<package id="YamlDotNet" version="12.3.1" targetFramework="net462" />
</packages>

View File

@ -0,0 +1,38 @@
using System;
namespace LANCommander.Models
{
public class GameManifest
{
public string Title { get; set; }
public string SortTitle { get; set; }
public string Description { get; set; }
public DateTime ReleasedOn { get; set; }
public string[] Genre { get; set; }
public string[] Tags { get; set; }
public string[] Publishers { get; set; }
public string[] Developers { get; set; }
public string Version { get; set; }
public string Icon { get; set; }
public GameAction[] Actions { get; set; }
public bool Singleplayer { get; set; }
public MultiplayerInfo LocalMultiplayer { get; set; }
public MultiplayerInfo LanMultiplayer { get; set; }
public MultiplayerInfo OnlineMultiplayer { get; set; }
}
public class GameAction
{
public string Name { get; set; }
public string Arguments { get; set; }
public string Path { get; set; }
public string WorkingDirectory { get; set; }
public bool IsPrimaryAction { get; set; }
}
public class MultiplayerInfo
{
public int MinPlayers { get; set; }
public int MaxPlayers { get; set; }
}
}