2023-01-14 21:09:45 +00:00
using LANCommander.PlaynitePlugin.Extensions ;
using LANCommander.SDK ;
2023-01-07 18:34:12 +00:00
using Playnite.SDK ;
2023-01-05 01:23:32 +00:00
using Playnite.SDK.Models ;
using Playnite.SDK.Plugins ;
using System ;
using System.Collections.Generic ;
2023-01-17 05:45:46 +00:00
using System.Collections.ObjectModel ;
2023-01-20 02:02:34 +00:00
using System.Diagnostics ;
2023-01-07 18:34:12 +00:00
using System.IO ;
2023-01-05 01:23:32 +00:00
using System.Linq ;
2023-01-16 02:45:37 +00:00
using System.Net.NetworkInformation ;
2023-01-05 01:23:32 +00:00
using System.Text ;
using System.Threading.Tasks ;
2023-01-15 19:33:04 +00:00
using System.Windows ;
2023-01-05 01:23:32 +00:00
using System.Windows.Controls ;
2023-01-20 02:02:34 +00:00
using System.Windows.Media ;
2023-01-07 18:34:12 +00:00
using YamlDotNet.Serialization ;
using YamlDotNet.Serialization.NamingConventions ;
using PN = Playnite ;
2023-01-05 01:23:32 +00:00
2023-01-08 18:09:57 +00:00
namespace LANCommander.PlaynitePlugin
2023-01-05 01:23:32 +00:00
{
2023-01-14 21:15:31 +00:00
public class LANCommanderLibraryPlugin : LibraryPlugin
2023-01-05 01:23:32 +00:00
{
public static readonly ILogger Logger = LogManager . GetLogger ( ) ;
2023-01-14 21:16:13 +00:00
internal LANCommanderSettingsViewModel Settings { get ; set ; }
2023-01-05 07:07:17 +00:00
internal LANCommanderClient LANCommander { get ; set ; }
2023-01-15 10:56:56 +00:00
internal PowerShellRuntime PowerShellRuntime { get ; set ; }
2023-01-05 01:23:32 +00:00
public override Guid Id { get ; } = Guid . Parse ( "48e1bac7-e0a0-45d7-ba83-36f5e9e959fc" ) ;
public override string Name = > "LANCommander" ;
2023-01-14 21:17:38 +00:00
public override LibraryClient Client { get ; } = new LANCommanderLibraryClient ( ) ;
2023-01-05 01:23:32 +00:00
2023-01-14 21:15:31 +00:00
public LANCommanderLibraryPlugin ( IPlayniteAPI api ) : base ( api )
2023-01-05 01:23:32 +00:00
{
Properties = new LibraryPluginProperties
{
HasSettings = true ,
} ;
2023-01-07 18:34:12 +00:00
2023-01-14 21:16:13 +00:00
Settings = new LANCommanderSettingsViewModel ( this ) ;
2023-01-12 02:48:39 +00:00
LANCommander = new LANCommanderClient ( Settings . ServerAddress ) ;
LANCommander . Token = new SDK . Models . AuthToken ( )
{
AccessToken = Settings . AccessToken ,
RefreshToken = Settings . RefreshToken ,
} ;
2023-01-15 10:56:56 +00:00
PowerShellRuntime = new PowerShellRuntime ( ) ;
2023-01-05 01:23:32 +00:00
}
public override IEnumerable < GameMetadata > GetGames ( LibraryGetGamesArgs args )
{
2023-01-07 20:32:52 +00:00
var gameMetadata = new List < GameMetadata > ( ) ;
2023-01-15 20:18:26 +00:00
if ( ! LANCommander . ValidateToken ( LANCommander . Token ) )
{
try
{
var response = LANCommander . RefreshToken ( LANCommander . Token ) ;
LANCommander . Token . AccessToken = response . AccessToken ;
LANCommander . Token . RefreshToken = response . RefreshToken ;
if ( ! LANCommander . ValidateToken ( LANCommander . Token ) )
{
throw new Exception ( ) ;
}
}
catch
{
ShowAuthenticationWindow ( ) ;
}
}
2023-01-05 07:07:17 +00:00
try
2023-01-05 02:31:02 +00:00
{
2023-01-06 08:39:00 +00:00
var games = LANCommander
2023-01-17 01:56:13 +00:00
. GetGames ( )
. Where ( g = > g . Archives ! = null & & g . Archives . Count ( ) > 0 ) ;
2023-01-07 20:32:52 +00:00
foreach ( var game in games )
{
2023-01-14 21:09:45 +00:00
var manifest = LANCommander . GetGameManifest ( game . Id ) ;
2023-01-07 20:32:52 +00:00
var existingGame = PlayniteApi . Database . Games . FirstOrDefault ( g = > g . GameId = = game . Id . ToString ( ) & & g . PluginId = = Id & & g . IsInstalled ) ;
2023-01-17 05:49:07 +00:00
if ( existingGame ! = null )
{
UpdateGame ( manifest , game . Id ) ;
continue ;
}
2023-01-07 20:32:52 +00:00
var metadata = new GameMetadata ( )
2023-01-06 08:39:00 +00:00
{
2023-01-16 17:32:47 +00:00
IsInstalled = false ,
2023-01-14 21:09:45 +00:00
Name = manifest . Title ,
SortingName = manifest . SortTitle ,
Description = manifest . Description ,
2023-01-07 20:32:52 +00:00
GameId = game . Id . ToString ( ) ,
2023-01-14 21:09:45 +00:00
ReleaseDate = new ReleaseDate ( manifest . ReleasedOn ) ,
//Version = game.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault().Version,
2023-01-17 23:09:42 +00:00
Icon = new MetadataFile ( $"{Settings.ServerAddress}{manifest.Icon}" ) ,
2023-01-17 05:45:46 +00:00
GameActions = game . Actions . OrderBy ( a = > a . SortOrder ) . Select ( a = > new PN . SDK . Models . GameAction ( )
2023-01-16 17:32:47 +00:00
{
Name = a . Name ,
Arguments = a . Arguments ,
Path = a . Path ,
WorkingDir = a . WorkingDirectory ,
IsPlayAction = a . PrimaryAction
} ) . ToList ( )
2023-01-07 20:32:52 +00:00
} ;
2023-01-14 21:09:45 +00:00
if ( manifest . Genre ! = null & & manifest . Genre . Count ( ) > 0 )
metadata . Genres = new HashSet < MetadataProperty > ( manifest . Genre . Select ( g = > new MetadataNameProperty ( g ) ) ) ;
if ( manifest . Developers ! = null & & manifest . Developers . Count ( ) > 0 )
metadata . Developers = new HashSet < MetadataProperty > ( manifest . Developers . Select ( d = > new MetadataNameProperty ( d ) ) ) ;
if ( manifest . Publishers ! = null & & manifest . Publishers . Count ( ) > 0 )
metadata . Publishers = new HashSet < MetadataProperty > ( manifest . Publishers . Select ( p = > new MetadataNameProperty ( p ) ) ) ;
if ( manifest . Tags ! = null & & manifest . Tags . Count ( ) > 0 )
metadata . Tags = new HashSet < MetadataProperty > ( manifest . Tags . Select ( t = > new MetadataNameProperty ( t ) ) ) ;
metadata . Features = new HashSet < MetadataProperty > ( ) ;
if ( manifest . Singleplayer )
metadata . Features . Add ( new MetadataNameProperty ( "Singleplayer" ) ) ;
if ( manifest . LocalMultiplayer ! = null )
metadata . Features . Add ( new MetadataNameProperty ( $"Local Multiplayer {manifest.LocalMultiplayer.GetPlayerCount()}" . Trim ( ) ) ) ;
if ( manifest . LanMultiplayer ! = null )
metadata . Features . Add ( new MetadataNameProperty ( $"LAN Multiplayer {manifest.LanMultiplayer.GetPlayerCount()}" . Trim ( ) ) ) ;
if ( manifest . OnlineMultiplayer ! = null )
metadata . Features . Add ( new MetadataNameProperty ( $"Online Multiplayer {manifest.OnlineMultiplayer.GetPlayerCount()}" . Trim ( ) ) ) ;
2023-01-07 20:32:52 +00:00
gameMetadata . Add ( metadata ) ;
} ;
2023-01-17 05:45:46 +00:00
2023-01-05 07:07:17 +00:00
}
2023-01-07 04:12:03 +00:00
catch ( Exception ex )
2023-01-05 07:07:17 +00:00
{
2023-01-07 20:32:52 +00:00
2023-01-05 07:07:17 +00:00
}
2023-01-07 20:32:52 +00:00
return gameMetadata ;
2023-01-05 01:23:32 +00:00
}
2023-01-07 04:12:03 +00:00
public override IEnumerable < InstallController > GetInstallActions ( GetInstallActionsArgs args )
{
if ( args . Game . PluginId ! = Id )
yield break ;
yield return new LANCommanderInstallController ( this , args . Game ) ;
}
2023-01-07 18:46:26 +00:00
public override IEnumerable < UninstallController > GetUninstallActions ( GetUninstallActionsArgs args )
{
if ( args . Game . PluginId ! = Id )
yield break ;
yield return new LANCommanderUninstallController ( this , args . Game ) ;
}
2023-01-15 10:56:56 +00:00
public override IEnumerable < GameMenuItem > GetGameMenuItems ( GetGameMenuItemsArgs args )
{
if ( args . Games . Count = = 1 & & args . Games . First ( ) . IsInstalled & & ! String . IsNullOrWhiteSpace ( args . Games . First ( ) . InstallDirectory ) )
{
var nameChangeScriptPath = PowerShellRuntime . GetScriptFilePath ( args . Games . First ( ) , SDK . Enums . ScriptType . NameChange ) ;
var keyChangeScriptPath = PowerShellRuntime . GetScriptFilePath ( args . Games . First ( ) , SDK . Enums . ScriptType . KeyChange ) ;
if ( File . Exists ( nameChangeScriptPath ) )
yield return new GameMenuItem
{
Description = "Change Player Name" ,
Action = ( nameChangeArgs ) = >
{
2023-01-16 17:31:38 +00:00
var result = PlayniteApi . Dialogs . SelectString ( "Enter your player name" , "Change Player Name" , Settings . PlayerName ) ;
if ( result . Result = = true )
PowerShellRuntime . RunScript ( nameChangeArgs . Games . First ( ) , SDK . Enums . ScriptType . NameChange , $@"""{result.SelectedString}""" ) ;
2023-01-15 10:56:56 +00:00
}
} ;
if ( File . Exists ( keyChangeScriptPath ) )
yield return new GameMenuItem
{
Description = "Change Game Key" ,
Action = ( keyChangeArgs ) = >
{
2023-01-16 02:45:37 +00:00
Guid gameId ;
if ( Guid . TryParse ( keyChangeArgs . Games . First ( ) . GameId , out gameId ) )
{
// NUKIEEEE
var newKey = LANCommander . GetNewKey ( gameId ) ;
if ( String . IsNullOrEmpty ( newKey ) )
PlayniteApi . Dialogs . ShowErrorMessage ( "There are no more keys available on the server." , "No Keys Available" ) ;
else
PowerShellRuntime . RunScript ( keyChangeArgs . Games . First ( ) , SDK . Enums . ScriptType . KeyChange , $@"""{newKey}""" ) ;
}
else
{
PlayniteApi . Dialogs . ShowErrorMessage ( "This game could not be found on the server. Your game may be corrupted." ) ;
}
2023-01-15 10:56:56 +00:00
}
} ;
}
}
// To add new main menu items override GetMainMenuItems
public override IEnumerable < MainMenuItem > GetMainMenuItems ( GetMainMenuItemsArgs args )
{
yield return new MainMenuItem
{
Description = "Change Player Name (All Games)" ,
Action = ( args2 ) = >
{
2023-01-20 02:02:34 +00:00
ShowNameChangeWindow ( ) ;
}
} ;
}
2023-01-15 10:56:56 +00:00
2023-01-20 02:02:34 +00:00
public override IEnumerable < TopPanelItem > GetTopPanelItems ( )
{
yield return new TopPanelItem
{
Title = "Click to change your name (All Games)" ,
Icon = new TextBlock
{
Text = Settings . PlayerName ,
FontSize = 16 ,
FontFamily = ResourceProvider . GetResource ( "FontIcoFont" ) as FontFamily ,
Padding = new Thickness ( 10 , 0 , 10 , 0 ) ,
} ,
Activated = ( ) = > {
ShowNameChangeWindow ( ) ;
2023-01-15 10:56:56 +00:00
}
} ;
}
2023-01-05 01:23:32 +00:00
public override ISettings GetSettings ( bool firstRunSettings )
{
2023-01-05 07:07:17 +00:00
return Settings ;
2023-01-05 01:23:32 +00:00
}
public override UserControl GetSettingsView ( bool firstRunView )
{
2023-01-14 21:19:14 +00:00
return new LANCommanderSettingsView ( this ) ;
2023-01-05 07:07:17 +00:00
}
2023-01-20 02:02:34 +00:00
public void ShowNameChangeWindow ( )
{
var result = PlayniteApi . Dialogs . SelectString ( "Enter your new player name. This will change your name across all installed games!" , "Enter Name" , Settings . PlayerName ) ;
if ( result . Result = = true )
{
// Check to make sure they're staying in ASCII encoding
2023-01-20 06:21:51 +00:00
if ( String . IsNullOrEmpty ( result . SelectedString ) | | result . SelectedString . Any ( c = > c > sbyte . MaxValue ) )
2023-01-20 02:02:34 +00:00
{
PlayniteApi . Dialogs . ShowErrorMessage ( "The name you supplied is invalid. Try again." ) ;
ShowNameChangeWindow ( ) ;
}
else
{
Settings . PlayerName = result . SelectedString ;
SavePluginSettings ( Settings ) ;
var games = PlayniteApi . Database . Games . Where ( g = > g . IsInstalled ) . ToList ( ) ;
PowerShellRuntime . RunScripts ( games , SDK . Enums . ScriptType . NameChange , Settings . PlayerName ) ;
}
}
}
2023-01-15 19:33:04 +00:00
public Window ShowAuthenticationWindow ( )
2023-01-05 07:07:17 +00:00
{
2023-01-15 19:33:04 +00:00
Window window = null ;
Application . Current . Dispatcher . Invoke ( ( Action ) delegate
2023-01-05 07:07:17 +00:00
{
2023-01-15 19:33:04 +00:00
window = PlayniteApi . Dialogs . CreateWindow ( new WindowCreationOptions ( )
{
ShowMinimizeButton = false ,
} ) ;
2023-01-05 07:07:17 +00:00
2023-01-15 19:33:04 +00:00
window . Title = "Authenticate to LANCommander" ;
2023-01-15 20:18:26 +00:00
window . Width = 400 ;
window . Height = 230 ;
2023-01-15 19:33:04 +00:00
window . Content = new Views . Authentication ( this ) ;
window . DataContext = new ViewModels . Authentication ( )
{
ServerAddress = Settings . ServerAddress
} ;
2023-01-05 07:07:17 +00:00
2023-01-15 19:33:04 +00:00
window . Owner = PlayniteApi . Dialogs . GetCurrentAppWindow ( ) ;
window . WindowStartupLocation = System . Windows . WindowStartupLocation . CenterOwner ;
window . ShowDialog ( ) ;
} ) ;
2023-01-06 08:39:00 +00:00
return window ;
2023-01-05 01:23:32 +00:00
}
2023-01-07 18:34:12 +00:00
2023-01-17 05:45:46 +00:00
public void UpdateGame ( SDK . GameManifest manifest , Guid gameId )
2023-01-07 18:34:12 +00:00
{
2023-01-17 05:45:46 +00:00
var game = PlayniteApi . Database . Games . First ( g = > g . GameId = = gameId . ToString ( ) ) ;
2023-01-07 18:34:12 +00:00
2023-01-17 23:09:42 +00:00
if ( game = = null )
return ;
2023-01-17 05:45:46 +00:00
if ( game . GameActions = = null )
game . GameActions = new ObservableCollection < PN . SDK . Models . GameAction > ( ) ;
else
game . GameActions . Clear ( ) ;
2023-01-07 18:34:12 +00:00
2023-01-17 23:09:42 +00:00
game . Icon = $"{Settings.ServerAddress}{manifest.Icon}" ;
2023-01-17 05:45:46 +00:00
foreach ( var action in manifest . Actions . OrderBy ( a = > a . SortOrder ) )
{
bool isFirstAction = ! manifest . Actions . Any ( a = > a . IsPrimaryAction ) & & manifest . Actions . First ( ) . Name = = action . Name ;
2023-01-07 20:32:52 +00:00
2023-01-17 05:45:46 +00:00
game . GameActions . Add ( new PN . SDK . Models . GameAction ( )
2023-01-07 18:34:12 +00:00
{
2023-01-17 05:45:46 +00:00
Name = action . Name ,
Arguments = action . Arguments ,
Path = PlayniteApi . ExpandGameVariables ( game , action . Path ? . Replace ( '/' , Path . DirectorySeparatorChar ) ) ,
2023-01-19 01:30:08 +00:00
WorkingDir = PlayniteApi . ExpandGameVariables ( game , action . WorkingDirectory ? . Replace ( '/' , Path . DirectorySeparatorChar ) ? ? game . InstallDirectory ) ,
2023-01-17 05:45:46 +00:00
IsPlayAction = action . IsPrimaryAction | | isFirstAction
} ) ;
}
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
#region Features
var singlePlayerFeature = PlayniteApi . Database . Features . FirstOrDefault ( f = > f . Name = = "Single Player" ) ;
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
if ( manifest . LanMultiplayer ! = null )
{
var multiplayerInfo = manifest . LanMultiplayer ;
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
string playerCount = multiplayerInfo . MinPlayers = = multiplayerInfo . MaxPlayers ? $"({multiplayerInfo.MinPlayers} players)" : $"({multiplayerInfo.MinPlayers} - {multiplayerInfo.MaxPlayers} players)" ;
string featureName = $"LAN Multiplayer {playerCount}" ;
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
if ( PlayniteApi . Database . Features . Any ( f = > f . Name = = featureName ) )
{
game . Features . Add ( PlayniteApi . Database . Features . FirstOrDefault ( f = > f . Name = = featureName ) ) ;
}
else
{
PlayniteApi . Database . Features . Add ( new GameFeature ( )
{
Name = featureName
} ) ;
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
game . Features . Add ( new GameFeature ( )
{
Name = $"LAN Multiplayer {playerCount}"
} ) ;
}
}
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
if ( manifest . LocalMultiplayer ! = null )
{
var multiplayerInfo = manifest . LocalMultiplayer ;
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
string playerCount = multiplayerInfo . MinPlayers = = multiplayerInfo . MaxPlayers ? $"({multiplayerInfo.MinPlayers} players)" : $"({multiplayerInfo.MinPlayers} - {multiplayerInfo.MaxPlayers} players)" ;
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
game . Features . Add ( new GameFeature ( )
{
Name = $"Local Multiplayer {playerCount}"
} ) ;
}
2023-01-12 02:48:39 +00:00
2023-01-17 05:45:46 +00:00
if ( manifest . OnlineMultiplayer ! = null )
{
var multiplayerInfo = manifest . OnlineMultiplayer ;
2023-01-07 20:32:52 +00:00
2023-01-17 05:45:46 +00:00
string playerCount = multiplayerInfo . MinPlayers = = multiplayerInfo . MaxPlayers ? $"({multiplayerInfo.MinPlayers} players)" : $"({multiplayerInfo.MinPlayers} - {multiplayerInfo.MaxPlayers} players)" ;
2023-01-07 18:34:12 +00:00
2023-01-17 05:45:46 +00:00
game . Features . Add ( new GameFeature ( )
{
Name = $"Online Multiplayer {playerCount}"
} ) ;
2023-01-07 18:34:12 +00:00
}
2023-01-17 05:45:46 +00:00
# endregion
PlayniteApi . Database . Games . Update ( game ) ;
2023-01-07 18:34:12 +00:00
}
2023-01-05 01:23:32 +00:00
}
}