Added ability for client to request the game manifest to provide metadata. Games can now be downloaded directly.
parent
1a6dff63b2
commit
3c62e795e5
|
@ -11,6 +11,8 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using ICSharpCode.SharpZipLib.Core;
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
namespace LANCommander.PlaynitePlugin
|
||||
{
|
||||
|
@ -39,6 +41,8 @@ namespace LANCommander.PlaynitePlugin
|
|||
InstallDirectory = installDirectory
|
||||
};
|
||||
|
||||
File.WriteAllText(Path.Combine(installDirectory, "_manifest.yml"), GetManifest(gameId));
|
||||
|
||||
InvokeOnInstalled(new GameInstalledEventArgs(installInfo));
|
||||
|
||||
Plugin.UpdateGamesFromManifest();
|
||||
|
@ -48,16 +52,14 @@ namespace LANCommander.PlaynitePlugin
|
|||
{
|
||||
string tempFile = String.Empty;
|
||||
|
||||
var archive = game.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault();
|
||||
|
||||
if (archive != null)
|
||||
if (game != null)
|
||||
{
|
||||
Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
|
||||
{
|
||||
progress.ProgressMaxValue = 100;
|
||||
progress.CurrentProgressValue = 0;
|
||||
|
||||
var destination = Plugin.LANCommander.DownloadArchive(archive.Id, (changed) =>
|
||||
var destination = Plugin.LANCommander.DownloadGame(game.Id, (changed) =>
|
||||
{
|
||||
progress.CurrentProgressValue = changed.ProgressPercentage;
|
||||
}, (complete) =>
|
||||
|
@ -82,7 +84,7 @@ namespace LANCommander.PlaynitePlugin
|
|||
return tempFile;
|
||||
}
|
||||
else
|
||||
throw new Exception("Game failed to download");
|
||||
throw new Exception("Game failed to download!");
|
||||
}
|
||||
|
||||
private string Extract(LANCommander.SDK.Models.Game game, string archivePath)
|
||||
|
@ -142,5 +144,18 @@ namespace LANCommander.PlaynitePlugin
|
|||
|
||||
return destination;
|
||||
}
|
||||
|
||||
private string GetManifest(Guid gameId)
|
||||
{
|
||||
var manifest = Plugin.LANCommander.GetGameManifest(gameId);
|
||||
|
||||
var serializer = new SerializerBuilder()
|
||||
.WithNamingConvention(PascalCaseNamingConvention.Instance)
|
||||
.Build();
|
||||
|
||||
var yaml = serializer.Serialize(manifest);
|
||||
|
||||
return yaml;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using LANCommander.SDK.Models;
|
||||
using LANCommander.SDK;
|
||||
using LANCommander.SDK.Models;
|
||||
using RestSharp;
|
||||
using RestSharp.Extensions;
|
||||
using System;
|
||||
|
@ -115,6 +116,16 @@ namespace LANCommander.PlaynitePlugin
|
|||
return GetRequest<Game>($"/api/Games/{id}");
|
||||
}
|
||||
|
||||
public GameManifest GetGameManifest(Guid id)
|
||||
{
|
||||
return GetRequest<GameManifest>($"/api/Games/{id}/Manifest");
|
||||
}
|
||||
|
||||
public string DownloadGame(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
|
||||
{
|
||||
return DownloadRequest($"/api/Games/{id}/Download", progressHandler, completeHandler);
|
||||
}
|
||||
|
||||
public string DownloadArchive(Guid id, Action<DownloadProgressChangedEventArgs> progressHandler, Action<AsyncCompletedEventArgs> completeHandler)
|
||||
{
|
||||
return DownloadRequest($"api/Archives/Download/{id}", progressHandler, completeHandler);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using LANCommander.Models;
|
||||
using LANCommander.PlaynitePlugin.Extensions;
|
||||
using LANCommander.SDK;
|
||||
using Playnite.SDK;
|
||||
using Playnite.SDK.Models;
|
||||
using Playnite.SDK.Plugins;
|
||||
|
@ -48,11 +49,11 @@ namespace LANCommander.PlaynitePlugin
|
|||
try
|
||||
{
|
||||
var games = LANCommander
|
||||
.GetGames()
|
||||
.Where(g => g.Archives != null && g.Archives.Count() > 0);
|
||||
.GetGames();
|
||||
|
||||
foreach (var game in games)
|
||||
{
|
||||
var manifest = LANCommander.GetGameManifest(game.Id);
|
||||
var existingGame = PlayniteApi.Database.Games.FirstOrDefault(g => g.GameId == game.Id.ToString() && g.PluginId == Id && g.IsInstalled);
|
||||
|
||||
var iconUri = new Uri(new Uri(Settings.ServerAddress), $"Games/GetIcon/{game.Id}");
|
||||
|
@ -60,15 +61,42 @@ namespace LANCommander.PlaynitePlugin
|
|||
var metadata = new GameMetadata()
|
||||
{
|
||||
IsInstalled = existingGame != null,
|
||||
Name = game.Title,
|
||||
SortingName = game.SortTitle,
|
||||
Description = game.Description,
|
||||
Name = manifest.Title,
|
||||
SortingName = manifest.SortTitle,
|
||||
Description = manifest.Description,
|
||||
GameId = game.Id.ToString(),
|
||||
ReleaseDate = new ReleaseDate(game.ReleasedOn),
|
||||
Version = game.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault().Version,
|
||||
Icon = new MetadataFile(iconUri.ToString())
|
||||
ReleaseDate = new ReleaseDate(manifest.ReleasedOn),
|
||||
//Version = game.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault().Version,
|
||||
Icon = new MetadataFile(iconUri.ToString()),
|
||||
Genres = new HashSet<MetadataProperty>()
|
||||
};
|
||||
|
||||
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()));
|
||||
|
||||
gameMetadata.Add(metadata);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace LANCommander.Models
|
||||
namespace LANCommander.SDK
|
||||
{
|
||||
public class GameManifest
|
||||
{
|
||||
|
@ -8,17 +9,19 @@ namespace LANCommander.Models
|
|||
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 IEnumerable<string> Genre { get; set; }
|
||||
public IEnumerable<string> Tags { get; set; }
|
||||
public IEnumerable<string> Publishers { get; set; }
|
||||
public IEnumerable<string> Developers { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Icon { get; set; }
|
||||
public GameAction[] Actions { get; set; }
|
||||
public IEnumerable<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 GameManifest() { }
|
||||
}
|
||||
|
||||
public class GameAction
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using LANCommander.Data;
|
||||
using LANCommander.Data.Models;
|
||||
using LANCommander.Extensions;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.SDK;
|
||||
using LANCommander.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
@ -30,5 +33,36 @@ namespace LANCommander.Controllers.Api
|
|||
{
|
||||
return await GameService.Get(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet("{id}/Manifest")]
|
||||
public async Task<GameManifest> GetManifest(Guid id)
|
||||
{
|
||||
var manifest = await GameService.GetManifest(id);
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
[HttpGet("{id}/Download")]
|
||||
public async Task<IActionResult> Download(Guid id)
|
||||
{
|
||||
var game = await GameService.Get(id);
|
||||
|
||||
if (game == null)
|
||||
return NotFound();
|
||||
|
||||
if (game.Archives == null || game.Archives.Count == 0)
|
||||
return NotFound();
|
||||
|
||||
var archive = game.Archives.OrderByDescending(a => a.CreatedOn).First();
|
||||
|
||||
var filename = Path.Combine("Upload", archive.ObjectKey);
|
||||
|
||||
if (!System.IO.File.Exists(filename))
|
||||
return NotFound();
|
||||
|
||||
return File(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream", $"{game.Title.SanitizeFilename()}.zip");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using LANCommander.Data.Models;
|
||||
using LANCommander.Extensions;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.SDK;
|
||||
using LANCommander.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
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; }
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using LANCommander.Data.Models;
|
|||
using LANCommander.Extensions;
|
||||
using LANCommander.Helpers;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.SDK;
|
||||
using System.IO.Compression;
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
using LANCommander.Data;
|
||||
using LANCommander.Data.Enums;
|
||||
using LANCommander.Data.Models;
|
||||
using LANCommander.Extensions;
|
||||
using LANCommander.Helpers;
|
||||
using LANCommander.Models;
|
||||
using LANCommander.SDK;
|
||||
using System.Drawing;
|
||||
|
||||
namespace LANCommander.Services
|
||||
|
@ -23,6 +26,86 @@ namespace LANCommander.Services
|
|||
await base.Delete(game);
|
||||
}
|
||||
|
||||
public async Task<GameManifest> GetManifest(Guid id)
|
||||
{
|
||||
var game = await Get(id);
|
||||
|
||||
if (game == null)
|
||||
return null;
|
||||
|
||||
var manifest = new GameManifest()
|
||||
{
|
||||
Title = game.Title,
|
||||
SortTitle = game.SortTitle,
|
||||
Description = game.Description,
|
||||
ReleasedOn = game.ReleasedOn.GetValueOrDefault(),
|
||||
Singleplayer = game.Singleplayer,
|
||||
};
|
||||
|
||||
if (game.Genres != null && game.Genres.Count > 0)
|
||||
manifest.Genre = game.Genres.Select(g => g.Name).ToArray();
|
||||
|
||||
if (game.Tags != null && game.Tags.Count > 0)
|
||||
manifest.Tags = game.Tags.Select(g => g.Name).ToArray();
|
||||
|
||||
if (game.Publishers != null && game.Publishers.Count > 0)
|
||||
manifest.Publishers = game.Publishers.Select(g => g.Name).ToArray();
|
||||
|
||||
if (game.Developers != null && game.Developers.Count > 0)
|
||||
manifest.Developers = game.Developers.Select(g => g.Name).ToArray();
|
||||
|
||||
if (game.Archives != null && game.Archives.Count > 0)
|
||||
manifest.Version = game.Archives.OrderByDescending(a => a.CreatedOn).First().Version;
|
||||
|
||||
try
|
||||
{
|
||||
manifest.Icon = Convert.ToBase64String(GetIcon(game));
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (game.Actions != null && game.Actions.Count > 0)
|
||||
{
|
||||
manifest.Actions = game.Actions.Select(a => new GameAction()
|
||||
{
|
||||
Name = a.Name,
|
||||
Arguments = a.Arguments,
|
||||
Path = a.Path,
|
||||
WorkingDirectory = a.WorkingDirectory,
|
||||
IsPrimaryAction = a.PrimaryAction
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
if (game.MultiplayerModes != null && game.MultiplayerModes.Count > 0)
|
||||
{
|
||||
var local = game.MultiplayerModes.FirstOrDefault(m => m.Type == MultiplayerType.Local);
|
||||
var lan = game.MultiplayerModes.FirstOrDefault(m => m.Type == MultiplayerType.Lan);
|
||||
var online = game.MultiplayerModes.FirstOrDefault(m => m.Type == MultiplayerType.Online);
|
||||
|
||||
if (local != null)
|
||||
manifest.LocalMultiplayer = new MultiplayerInfo()
|
||||
{
|
||||
MinPlayers = local.MinPlayers,
|
||||
MaxPlayers = local.MaxPlayers,
|
||||
};
|
||||
|
||||
if (lan != null)
|
||||
manifest.LanMultiplayer = new MultiplayerInfo()
|
||||
{
|
||||
MinPlayers = lan.MinPlayers,
|
||||
MaxPlayers = lan.MaxPlayers,
|
||||
};
|
||||
|
||||
if (online != null)
|
||||
manifest.LocalMultiplayer = new MultiplayerInfo()
|
||||
{
|
||||
MaxPlayers = online.MinPlayers,
|
||||
MinPlayers = online.MaxPlayers,
|
||||
};
|
||||
}
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
public byte[] GetIcon(Game game)
|
||||
{
|
||||
var cachedPath = $"Icon/{game.Id}.png";
|
||||
|
|
Loading…
Reference in New Issue