Added game manifest model. Reworked settings to be a bit more universal across the extension. Made server URL configurable.
This commit is contained in:
		
							parent
							
								
									cf326dd5ca
								
							
						
					
					
						commit
						787a983c03
					
				
					 10 changed files with 188 additions and 55 deletions
				
			
		|  | @ -82,6 +82,9 @@ | ||||||
|     <Reference Include="System.Net.Http" /> |     <Reference Include="System.Net.Http" /> | ||||||
|     <Reference Include="System.Xml" /> |     <Reference Include="System.Xml" /> | ||||||
|     <Reference Include="WindowsBase" /> |     <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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Compile Include="InstallController.cs" /> |     <Compile Include="InstallController.cs" /> | ||||||
|  |  | ||||||
|  | @ -14,12 +14,12 @@ namespace LANCommander.Playnite.Extension | ||||||
| { | { | ||||||
|     internal class LANCommanderClient |     internal class LANCommanderClient | ||||||
|     { |     { | ||||||
|         private readonly RestClient Client; |         public readonly RestClient Client; | ||||||
|         public AuthToken Token; |         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) |         private T PostRequest<T>(string route, object body) | ||||||
|  | @ -89,6 +89,9 @@ namespace LANCommander.Playnite.Extension | ||||||
| 
 | 
 | ||||||
|             var response = Client.Post<AuthResponse>(request); |             var response = Client.Post<AuthResponse>(request); | ||||||
| 
 | 
 | ||||||
|  |             if (response.StatusCode != HttpStatusCode.OK) | ||||||
|  |                 throw new WebException(response.ErrorMessage); | ||||||
|  | 
 | ||||||
|             return response.Data; |             return response.Data; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,19 +1,24 @@ | ||||||
| using Playnite.SDK; | using LANCommander.Models; | ||||||
|  | using Playnite.SDK; | ||||||
| using Playnite.SDK.Models; | using Playnite.SDK.Models; | ||||||
| using Playnite.SDK.Plugins; | using Playnite.SDK.Plugins; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using System.IO; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Text; | using System.Text; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
|  | using YamlDotNet.Serialization; | ||||||
|  | using YamlDotNet.Serialization.NamingConventions; | ||||||
|  | using PN = Playnite; | ||||||
| 
 | 
 | ||||||
| namespace LANCommander.Playnite.Extension | namespace LANCommander.Playnite.Extension | ||||||
| { | { | ||||||
|     public class PlayniteLibraryPlugin : LibraryPlugin |     public class PlayniteLibraryPlugin : LibraryPlugin | ||||||
|     { |     { | ||||||
|         public static readonly ILogger Logger = LogManager.GetLogger(); |         public static readonly ILogger Logger = LogManager.GetLogger(); | ||||||
|         private PlayniteSettingsViewModel Settings { get; set; } |         internal PlayniteSettingsViewModel Settings { get; set; } | ||||||
|         internal LANCommanderClient LANCommander { get; set; } |         internal LANCommanderClient LANCommander { get; set; } | ||||||
| 
 | 
 | ||||||
|         public override Guid Id { get; } = Guid.Parse("48e1bac7-e0a0-45d7-ba83-36f5e9e959fc"); |         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) |         public PlayniteLibraryPlugin(IPlayniteAPI api) : base(api) | ||||||
|         { |         { | ||||||
|             LANCommander = new LANCommanderClient(); |  | ||||||
|             Settings = new PlayniteSettingsViewModel(this); |  | ||||||
|             Properties = new LibraryPluginProperties |             Properties = new LibraryPluginProperties | ||||||
|             { |             { | ||||||
|                 HasSettings = true, |                 HasSettings = true, | ||||||
|             }; |             }; | ||||||
|  | 
 | ||||||
|  |             LoadSettings(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public override IEnumerable<GameMetadata> GetGames(LibraryGetGamesArgs args) |         public override IEnumerable<GameMetadata> GetGames(LibraryGetGamesArgs args) | ||||||
|         { |         { | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var token = new SDK.Models.AuthToken() |                 var syncedGames = PlayniteApi.Database.Games; | ||||||
|                 { |  | ||||||
|                     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 games = LANCommander |                 var games = LANCommander | ||||||
|                     .GetGames() |                     .GetGames() | ||||||
|  | @ -101,6 +84,52 @@ namespace LANCommander.Playnite.Extension | ||||||
|             return new PlayniteSettingsView(this); |             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() |         public System.Windows.Window ShowAuthenticationWindow() | ||||||
|         { |         { | ||||||
|             var window = PlayniteApi.Dialogs.CreateWindow(new WindowCreationOptions() |             var window = PlayniteApi.Dialogs.CreateWindow(new WindowCreationOptions() | ||||||
|  | @ -119,5 +148,44 @@ namespace LANCommander.Playnite.Extension | ||||||
| 
 | 
 | ||||||
|             return window; |             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."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ namespace LANCommander.Playnite.Extension | ||||||
|     { |     { | ||||||
|         private readonly PlayniteLibraryPlugin Plugin; |         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 AccessToken { get; set; } = String.Empty; | ||||||
|         public string RefreshToken { get; set; } = String.Empty; |         public string RefreshToken { get; set; } = String.Empty; | ||||||
| 
 | 
 | ||||||
|  | @ -25,14 +25,9 @@ namespace LANCommander.Playnite.Extension | ||||||
|         { |         { | ||||||
|             Plugin = plugin; |             Plugin = plugin; | ||||||
| 
 | 
 | ||||||
|             var savedSettings = Plugin.LoadPluginSettings<PlayniteSettingsViewModel>(); |             ServerAddress = Plugin.Settings.ServerAddress; | ||||||
| 
 |             AccessToken = Plugin.Settings.AccessToken; | ||||||
|             if (savedSettings != null) |             RefreshToken = Plugin.Settings.RefreshToken; | ||||||
|             { |  | ||||||
|                 ServerUrl = savedSettings.ServerUrl; |  | ||||||
|                 AccessToken = savedSettings.AccessToken; |  | ||||||
|                 RefreshToken = savedSettings.RefreshToken; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void BeginEdit() |         public void BeginEdit() | ||||||
|  | @ -47,7 +42,9 @@ namespace LANCommander.Playnite.Extension | ||||||
| 
 | 
 | ||||||
|         public void EndEdit() |         public void EndEdit() | ||||||
|         { |         { | ||||||
|             // Plugin.SavePluginSettings(this); |             Plugin.Settings.ServerAddress = ServerAddress; | ||||||
|  | 
 | ||||||
|  |             Plugin.SaveSettings(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public bool VerifySettings(out List<string> errors) |         public bool VerifySettings(out List<string> errors) | ||||||
|  |  | ||||||
|  | @ -27,23 +27,40 @@ namespace LANCommander.Playnite.Extension | ||||||
| 
 | 
 | ||||||
|             InitializeComponent(); |             InitializeComponent(); | ||||||
| 
 | 
 | ||||||
|             var settings = new PlayniteSettingsViewModel(plugin); |             UpdateAuthenticationButtonVisibility(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|             if (Plugin.LANCommander.ValidateToken(new AuthToken() |         private void UpdateAuthenticationButtonVisibility() | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 if (Plugin.LANCommander.ValidateToken(new AuthToken() | ||||||
|  |                 { | ||||||
|  |                     AccessToken = Plugin.Settings.AccessToken, | ||||||
|  |                     RefreshToken = Plugin.Settings.RefreshToken, | ||||||
|  |                 })) | ||||||
|  |                 { | ||||||
|  |                     var authenticateButton = FindName("AuthenticateButton") as Button; | ||||||
|  | 
 | ||||||
|  |                     authenticateButton.Visibility = Visibility.Hidden; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             catch | ||||||
|             { |             { | ||||||
|                 AccessToken = settings.AccessToken, |  | ||||||
|                 RefreshToken = settings.RefreshToken, |  | ||||||
|             })) |  | ||||||
|             { |  | ||||||
|                 var authenticateButton = FindName("AuthenticateButton") as Button; |  | ||||||
| 
 | 
 | ||||||
|                 authenticateButton.Visibility = Visibility.Hidden; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void AuthenticateButton_Click(object sender, RoutedEventArgs e) |         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(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ namespace LANCommander.Playnite.Extension.ViewModels | ||||||
| { | { | ||||||
|     internal class Authentication |     internal class Authentication | ||||||
|     { |     { | ||||||
|  |         public string ServerAddress { get; set; } | ||||||
|         public string UserName { get; set; } |         public string UserName { get; set; } | ||||||
|         public string Password { get; set; } |         public string Password { get; set; } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -13,6 +13,8 @@ | ||||||
|         </Style> |         </Style> | ||||||
|     </d:DesignerProperties.DesignStyle> |     </d:DesignerProperties.DesignStyle> | ||||||
|     <StackPanel Margin="20"> |     <StackPanel Margin="20"> | ||||||
|  |         <TextBlock Text="Server Address" /> | ||||||
|  |         <TextBox Name="ServerAddress" Text="{Binding ServerAddress}" KeyDown="TextBox_KeyDown" /> | ||||||
|         <TextBlock Text="Username"/> |         <TextBlock Text="Username"/> | ||||||
|         <TextBox Name="Username" Text="{Binding UserName}" KeyDown="TextBox_KeyDown" /> |         <TextBox Name="Username" Text="{Binding UserName}" KeyDown="TextBox_KeyDown" /> | ||||||
|         <TextBlock Text="Password" /> |         <TextBlock Text="Password" /> | ||||||
|  |  | ||||||
|  | @ -21,12 +21,10 @@ namespace LANCommander.Playnite.Extension.Views | ||||||
|     { |     { | ||||||
|         private PlayniteLibraryPlugin Plugin; |         private PlayniteLibraryPlugin Plugin; | ||||||
|         private ViewModels.Authentication Context { get { return (ViewModels.Authentication)DataContext; } } |         private ViewModels.Authentication Context { get { return (ViewModels.Authentication)DataContext; } } | ||||||
|         private PlayniteSettingsViewModel Settings { get; set; } |  | ||||||
| 
 | 
 | ||||||
|         public Authentication(PlayniteLibraryPlugin plugin) |         public Authentication(PlayniteLibraryPlugin plugin) | ||||||
|         { |         { | ||||||
|             Plugin = plugin; |             Plugin = plugin; | ||||||
|             Settings = Plugin.GetSettings(false) as PlayniteSettingsViewModel; |  | ||||||
| 
 | 
 | ||||||
|             InitializeComponent(); |             InitializeComponent(); | ||||||
|         } |         } | ||||||
|  | @ -56,16 +54,21 @@ namespace LANCommander.Playnite.Extension.Views | ||||||
|         { |         { | ||||||
|             try |             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); |                 var response = Plugin.LANCommander.Authenticate(Context.UserName, Context.Password); | ||||||
| 
 | 
 | ||||||
|                 Settings.AccessToken = response.AccessToken; |                 Plugin.Settings.ServerAddress = Context.ServerAddress; | ||||||
|                 Settings.RefreshToken = response.RefreshToken; |                 Plugin.Settings.AccessToken = response.AccessToken; | ||||||
|  |                 Plugin.Settings.RefreshToken = response.RefreshToken; | ||||||
| 
 | 
 | ||||||
|                 // Probably unneeded, but why not be more secure? |                 // Probably unneeded, but why not be more secure? | ||||||
|                 Context.Password = String.Empty; |                 Context.Password = String.Empty; | ||||||
| 
 | 
 | ||||||
|                 Plugin.SavePluginSettings(Settings); |                 Plugin.SaveSettings(); | ||||||
|                 //Plugin.Settings = Plugin.LoadPluginSettings<PlayniteSettingsViewModel>(); |  | ||||||
| 
 | 
 | ||||||
|                 Window.GetWindow(this).Close(); |                 Window.GetWindow(this).Close(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -12,4 +12,5 @@ | ||||||
|   <package id="System.Text.Json" version="5.0.1" targetFramework="net462" /> |   <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.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net462" /> | ||||||
|   <package id="System.ValueTuple" version="4.5.0" targetFramework="net462" /> |   <package id="System.ValueTuple" version="4.5.0" targetFramework="net462" /> | ||||||
|  |   <package id="YamlDotNet" version="12.3.1" targetFramework="net462" /> | ||||||
| </packages> | </packages> | ||||||
							
								
								
									
										38
									
								
								LANCommander.SDK/Models/GameManifest.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								LANCommander.SDK/Models/GameManifest.cs
									
										
									
									
									
										Normal 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; } | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Pat Hartl
						Pat Hartl