Refactor launcher library importing, manifests
Switched the library importing in the launcher to work based on a queue. As a new game is added to the queue, it should find any related data and also add it to the queue. This should result in an easier to maintain importer while reducing the load on the launcher's DAL. This may result in more RAM usage while importing. Local manifests have also been refactored to match manifests in import/export LCX files, removing the old manifest format. This is a large breaking change that will probably break existing game installations. A migration will probably have to be created.
This commit is contained in:
parent
b7433a2da1
commit
6dfc0906ac
60 changed files with 2229 additions and 984 deletions
|
|
@ -1,16 +0,0 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace LANCommander.Launcher.Data.Enums
|
||||
{
|
||||
public enum GameType
|
||||
{
|
||||
[Display(Name = "Main Game")]
|
||||
MainGame,
|
||||
Expansion,
|
||||
[Display(Name = "Standalone Expansion")]
|
||||
StandaloneExpansion,
|
||||
Mod,
|
||||
[Display(Name = "Standalone Mod")]
|
||||
StandaloneMod
|
||||
}
|
||||
}
|
||||
852
LANCommander.Launcher.Data/Migrations/20251130001620_AddImportedOn.Designer.cs
generated
Normal file
852
LANCommander.Launcher.Data/Migrations/20251130001620_AddImportedOn.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,852 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using LANCommander.Launcher.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20251130001620_AddImportedOn")]
|
||||
partial class AddImportedOn
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.9");
|
||||
|
||||
modelBuilder.Entity("CategoryGame", b =>
|
||||
{
|
||||
b.Property<Guid>("CategoriesId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("GamesId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("CategoriesId", "GamesId");
|
||||
|
||||
b.HasIndex("GamesId");
|
||||
|
||||
b.ToTable("CategoryGame");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CollectionGame", b =>
|
||||
{
|
||||
b.Property<Guid>("CollectionId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("CollectionId", "GameId");
|
||||
|
||||
b.HasIndex("GameId");
|
||||
|
||||
b.ToTable("CollectionGame");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDeveloper", b =>
|
||||
{
|
||||
b.Property<Guid>("DeveloperId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("DeveloperId", "GameId");
|
||||
|
||||
b.HasIndex("GameId");
|
||||
|
||||
b.ToTable("GameDeveloper");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameGenre", b =>
|
||||
{
|
||||
b.Property<Guid>("GamesId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("GenresId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("GamesId", "GenresId");
|
||||
|
||||
b.HasIndex("GenresId");
|
||||
|
||||
b.ToTable("GameGenre");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GamePlatform", b =>
|
||||
{
|
||||
b.Property<Guid>("GamesId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("PlatformsId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("GamesId", "PlatformsId");
|
||||
|
||||
b.HasIndex("PlatformsId");
|
||||
|
||||
b.ToTable("GamePlatform");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GamePublisher", b =>
|
||||
{
|
||||
b.Property<Guid>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("PublisherId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("GameId", "PublisherId");
|
||||
|
||||
b.HasIndex("PublisherId");
|
||||
|
||||
b.ToTable("GamePublisher");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameRedistributable", b =>
|
||||
{
|
||||
b.Property<Guid>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("RedistributableId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("GameId", "RedistributableId");
|
||||
|
||||
b.HasIndex("RedistributableId");
|
||||
|
||||
b.ToTable("GameRedistributable");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameTag", b =>
|
||||
{
|
||||
b.Property<Guid>("GamesId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("TagsId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("GamesId", "TagsId");
|
||||
|
||||
b.HasIndex("TagsId");
|
||||
|
||||
b.ToTable("GameTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("ParentId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Collection", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Collections");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Company", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Companies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Engines");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("BaseGameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("EngineId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long?>("IGDBId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("InstallDirectory")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Installed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("InstalledOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("InstalledVersion")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LatestVersion")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("ReleasedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Singleplayer")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SortTitle")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BaseGameId");
|
||||
|
||||
b.HasIndex("EngineId");
|
||||
|
||||
b.ToTable("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Genre", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Genres");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Library", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Libraries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Crc32")
|
||||
.IsRequired()
|
||||
.HasMaxLength(8)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("FileId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("MimeType")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SourceUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GameId");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Media");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("MaxPlayers")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("MinPlayers")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("NetworkProtocol")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Spectators")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GameId");
|
||||
|
||||
b.ToTable("MultiplayerModes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Platform", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Platforms");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.PlaySession", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("End")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("Start")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GameId");
|
||||
|
||||
b.ToTable("PlaySessions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Redistributable", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Redistributables");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Tag", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Tags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.User", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Alias")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LibraryGame", b =>
|
||||
{
|
||||
b.Property<Guid>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("LibraryId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("GameId", "LibraryId");
|
||||
|
||||
b.HasIndex("LibraryId");
|
||||
|
||||
b.ToTable("LibraryGame");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CategoryGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CollectionGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Collection", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDeveloper", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("DeveloperId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameGenre", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Genre", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GenresId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GamePlatform", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Platform", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PlatformsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GamePublisher", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Company", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("PublisherId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameRedistributable", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Redistributable", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RedistributableId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameTag", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GamesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Tag", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TagsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Category", "Parent")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("ParentId");
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "BaseGame")
|
||||
.WithMany("DependentGames")
|
||||
.HasForeignKey("BaseGameId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Engine", "Engine")
|
||||
.WithMany("Games")
|
||||
.HasForeignKey("EngineId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("BaseGame");
|
||||
|
||||
b.Navigation("Engine");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Library", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.User", "User")
|
||||
.WithOne("Library")
|
||||
.HasForeignKey("LANCommander.Launcher.Data.Models.Library", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Media", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
.WithMany("Media")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.User", "User")
|
||||
.WithOne("Avatar")
|
||||
.HasForeignKey("LANCommander.Launcher.Data.Models.Media", "UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Game");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.MultiplayerMode", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
.WithMany("MultiplayerModes")
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.PlaySession", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", "Game")
|
||||
.WithMany("PlaySessions")
|
||||
.HasForeignKey("GameId");
|
||||
|
||||
b.Navigation("Game");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LibraryGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Game", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("GameId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Launcher.Data.Models.Library", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("LibraryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Category", b =>
|
||||
{
|
||||
b.Navigation("Children");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Engine", b =>
|
||||
{
|
||||
b.Navigation("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.Game", b =>
|
||||
{
|
||||
b.Navigation("DependentGames");
|
||||
|
||||
b.Navigation("Media");
|
||||
|
||||
b.Navigation("MultiplayerModes");
|
||||
|
||||
b.Navigation("PlaySessions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Launcher.Data.Models.User", b =>
|
||||
{
|
||||
b.Navigation("Avatar");
|
||||
|
||||
b.Navigation("Library");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Launcher.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddImportedOn : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Users",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Tags",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Redistributables",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "PlaySessions",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Platforms",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "MultiplayerModes",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Media",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Libraries",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Genres",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Games",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "TEXT",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Engines",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Companies",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Collections",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Categories",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Tags");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Redistributables");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "PlaySessions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Platforms");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "MultiplayerModes");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Media");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Libraries");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Genres");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Engines");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Companies");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Collections");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ImportedOn",
|
||||
table: "Categories");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "ImportedOn",
|
||||
table: "Games",
|
||||
type: "TEXT",
|
||||
nullable: true,
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "TEXT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.1");
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.9");
|
||||
|
||||
modelBuilder.Entity("CategoryGame", b =>
|
||||
{
|
||||
|
|
@ -146,6 +146,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -172,6 +175,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -193,6 +199,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -214,6 +223,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -247,7 +259,7 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<long?>("IGDBId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("ImportedOn")
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("InstallDirectory")
|
||||
|
|
@ -305,6 +317,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -326,6 +341,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
|
@ -360,6 +378,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<Guid?>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("MimeType")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -406,6 +427,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<Guid?>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("MaxPlayers")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
|
|
@ -440,6 +464,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -467,6 +494,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<Guid?>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime?>("Start")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
|
@ -495,6 +525,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -519,6 +552,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -543,6 +579,9 @@ namespace LANCommander.Launcher.Data.Migrations
|
|||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("UpdatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ namespace LANCommander.Launcher.Data.Models
|
|||
{
|
||||
[Key]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Display(Name = "Imported On")]
|
||||
public DateTime ImportedOn { get; set; }
|
||||
|
||||
[Display(Name = "Created On")]
|
||||
public DateTime CreatedOn { get; set; }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using LANCommander.Launcher.Data.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LANCommander.SDK.Enums;
|
||||
|
||||
namespace LANCommander.Launcher.Data.Models
|
||||
{
|
||||
|
|
@ -23,8 +23,6 @@ namespace LANCommander.Launcher.Data.Models
|
|||
|
||||
[Display(Name = "Released On")]
|
||||
public DateTime? ReleasedOn { get; set; }
|
||||
|
||||
public DateTime? ImportedOn { get; set; }
|
||||
|
||||
public GameType Type { get; set; }
|
||||
public Guid? BaseGameId { get; set; }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using LANCommander.Launcher.Data.Enums;
|
||||
using LANCommander.SDK.Enums;
|
||||
using LANCommander.SDK.Enums;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using LANCommander.Launcher.Data.Enums;
|
||||
using LANCommander.SDK.Enums;
|
||||
using LANCommander.SDK.Enums;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace LANCommander.Launcher.Models
|
|||
{
|
||||
public class ActionSelectorDialogOptions
|
||||
{
|
||||
public IEnumerable<SDK.Models.Action> Actions { get; set; }
|
||||
public IEnumerable<SDK.Models.Manifest.Action> Actions { get; set; }
|
||||
public string Title { get; set; }
|
||||
public Game Game { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,14 +123,14 @@ namespace LANCommander.Launcher.Services
|
|||
|
||||
try
|
||||
{
|
||||
var game = await gameService.GetAsync(options.GameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(game.InstallDirectory, game.Id);
|
||||
/*var game = await gameService.GetAsync(options.GameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(game.InstallDirectory, game.Id);
|
||||
var action = manifest.Actions.FirstOrDefault(a => a.Id == options.ActionId);
|
||||
|
||||
if (action == null)
|
||||
action = manifest.Actions.OrderBy(a => a.SortOrder).FirstOrDefault(a => a.IsPrimaryAction);
|
||||
|
||||
await gameService.Run(game, action);
|
||||
await gameService.Run(game, action);*/
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -142,7 +142,7 @@ namespace LANCommander.Launcher.Services
|
|||
{
|
||||
Logger.LogInformation("Syncing games from server...");
|
||||
|
||||
importService.OnImportComplete += async () =>
|
||||
/*importService.OnImportComplete += async () =>
|
||||
{
|
||||
Logger.LogInformation("Sync complete!");
|
||||
};
|
||||
|
|
@ -150,7 +150,7 @@ namespace LANCommander.Launcher.Services
|
|||
importService.OnImportFailed += async (Exception ex) =>
|
||||
{
|
||||
Logger.LogError(ex, "Sync failed!");
|
||||
};
|
||||
};*/
|
||||
|
||||
await importService.ImportAsync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
namespace LANCommander.Launcher.Services.Exceptions;
|
||||
|
||||
public class ImportSkippedException<TRecord> : Exception where TRecord : class
|
||||
{
|
||||
public TRecord Record { get; set; }
|
||||
|
||||
public ImportSkippedException(TRecord record, string message) : base(message)
|
||||
{
|
||||
Record = record;
|
||||
}
|
||||
|
||||
public ImportSkippedException(TRecord record, string message, Exception innerException) : base(message,
|
||||
innerException)
|
||||
{
|
||||
Record = record;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
using LANCommander.Launcher.Data;
|
||||
using LANCommander.Launcher.Services.Import;
|
||||
using LANCommander.Launcher.Services.Import.Factories;
|
||||
using LANCommander.Launcher.Services.Import.Importers;
|
||||
using LANCommander.Launcher.Services.PowerShell;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
@ -17,7 +20,10 @@ namespace LANCommander.Launcher.Services.Extensions
|
|||
{
|
||||
public static IServiceCollection AddLANCommanderLauncher(this IServiceCollection services, Action<LANCommanderOptions> configure)
|
||||
{
|
||||
services.AddDbContext<DbContext, DatabaseContext>();
|
||||
services.AddDbContext<DbContext, DatabaseContext>(options =>
|
||||
{
|
||||
options.EnableSensitiveDataLogging();
|
||||
});
|
||||
|
||||
#region Register Client
|
||||
var options = new LANCommanderOptions();
|
||||
|
|
@ -55,6 +61,21 @@ namespace LANCommander.Launcher.Services.Extensions
|
|||
services.AddScoped<SaveService>();
|
||||
services.AddScoped<TagService>();
|
||||
services.AddScoped<UpdateService>();
|
||||
|
||||
#region Import
|
||||
|
||||
services.AddScoped<ImportContextFactory>();
|
||||
|
||||
services.AddScoped<CollectionImporter>();
|
||||
services.AddScoped<DeveloperImporter>();
|
||||
services.AddScoped<EngineImporter>();
|
||||
services.AddScoped<GameImporter>();
|
||||
services.AddScoped<GenreImporter>();
|
||||
services.AddScoped<MultiplayerModeImporter>();
|
||||
services.AddScoped<PlatformImporter>();
|
||||
services.AddScoped<PublisherImporter>();
|
||||
services.AddScoped<TagImporter>();
|
||||
#endregion
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using LANCommander.Launcher.Data.Models;
|
||||
using LANCommander.Launcher.Models;
|
||||
using LANCommander.SDK.Enums;
|
||||
using LANCommander.SDK.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
|
@ -116,7 +117,7 @@ namespace LANCommander.Launcher.Services
|
|||
if (Filter.Installed)
|
||||
items = items.Where(i => (i.DataItem as Game).Installed);
|
||||
|
||||
items = items.Where(i => (i.DataItem as Game).Type.ValueIsIn(Data.Enums.GameType.MainGame, Data.Enums.GameType.StandaloneExpansion, Data.Enums.GameType.StandaloneMod));
|
||||
items = items.Where(i => (i.DataItem as Game).Type.ValueIsIn(GameType.MainGame, GameType.StandaloneExpansion, GameType.StandaloneMod));
|
||||
|
||||
op.Complete();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace LANCommander.Launcher.Services
|
|||
}
|
||||
}
|
||||
|
||||
public async Task Run(Game game, SDK.Models.Action action)
|
||||
public async Task Run(Game game, SDK.Models.Manifest.Action action)
|
||||
{
|
||||
Guid userId;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Factories;
|
||||
|
||||
public class ImportContextFactory(IServiceProvider serviceProvider)
|
||||
{
|
||||
public ImportContext Create()
|
||||
{
|
||||
var scope = serviceProvider.CreateScope();
|
||||
|
||||
return scope.ServiceProvider.GetRequiredService<ImportContext>();
|
||||
}
|
||||
}
|
||||
9
LANCommander.Launcher.Services/Import/IImportItemInfo.cs
Normal file
9
LANCommander.Launcher.Services/Import/IImportItemInfo.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
namespace LANCommander.Launcher.Services.Import;
|
||||
|
||||
public interface IImportItemInfo
|
||||
{
|
||||
string Key { get; set; }
|
||||
string Type { get; set; }
|
||||
string Name { get; set; }
|
||||
bool Processed { get; set; }
|
||||
}
|
||||
11
LANCommander.Launcher.Services/Import/IImporter.cs
Normal file
11
LANCommander.Launcher.Services/Import/IImporter.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
namespace LANCommander.Launcher.Services.Import;
|
||||
|
||||
public interface IImporter<TRecord, TEntity> where TRecord : class
|
||||
{
|
||||
void UseContext(ImportContext importContext);
|
||||
Task<ImportItemInfo<TRecord>> GetImportInfoAsync(TRecord record);
|
||||
Task<bool> CanImportAsync(TRecord record);
|
||||
Task<TEntity> AddAsync(TRecord record);
|
||||
Task<TEntity> UpdateAsync(TRecord record);
|
||||
Task<bool> ExistsAsync(TRecord record);
|
||||
}
|
||||
150
LANCommander.Launcher.Services/Import/ImportContext.cs
Normal file
150
LANCommander.Launcher.Services/Import/ImportContext.cs
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
using LANCommander.Launcher.Services.Import.Importers;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import;
|
||||
|
||||
public class ImportContext
|
||||
{
|
||||
public IImportItemInfo CurrentItem { get; set; }
|
||||
public int Processed => _queue.Count(qi => qi.Processed);
|
||||
public int Total => _queue.Count;
|
||||
|
||||
public EventHandler OnImportStarted { get; set; }
|
||||
public EventHandler<ImportStatusUpdate> OnImportProgress { get; set; }
|
||||
public EventHandler OnImportCompleted { get; set; }
|
||||
|
||||
private List<IImportItemInfo> _queue { get; set; } = new();
|
||||
|
||||
#region Importers
|
||||
|
||||
private CollectionImporter _collections;
|
||||
private DeveloperImporter _developers;
|
||||
private EngineImporter _engines;
|
||||
private GameImporter _games;
|
||||
private GenreImporter _genres;
|
||||
private MultiplayerModeImporter _multiplayerModes;
|
||||
private PlatformImporter _platforms;
|
||||
private PublisherImporter _publishers;
|
||||
private TagImporter _tags;
|
||||
#endregion
|
||||
|
||||
public ImportContext(IServiceProvider serviceProvider)
|
||||
{
|
||||
_collections = serviceProvider.GetRequiredService<CollectionImporter>();
|
||||
_developers = serviceProvider.GetRequiredService<DeveloperImporter>();
|
||||
_engines = serviceProvider.GetRequiredService<EngineImporter>();
|
||||
_games = serviceProvider.GetRequiredService<GameImporter>();
|
||||
_genres = serviceProvider.GetRequiredService<GenreImporter>();
|
||||
_multiplayerModes = serviceProvider.GetRequiredService<MultiplayerModeImporter>();
|
||||
_platforms = serviceProvider.GetRequiredService<PlatformImporter>();
|
||||
_publishers = serviceProvider.GetRequiredService<PublisherImporter>();
|
||||
_tags = serviceProvider.GetRequiredService<TagImporter>();
|
||||
}
|
||||
|
||||
public async Task AddAsync(Game game)
|
||||
{
|
||||
foreach (var collection in game.Collections)
|
||||
if (!InQueue(collection, _collections) && await _collections.CanImportAsync(collection))
|
||||
_queue.Add(await _collections.GetImportInfoAsync(collection));
|
||||
|
||||
foreach (var developer in game.Developers)
|
||||
if (!InQueue(developer, _developers) && await _developers.CanImportAsync(developer))
|
||||
_queue.Add(await _developers.GetImportInfoAsync(developer));
|
||||
|
||||
if (!InQueue(game.Engine, _engines) && await _engines.CanImportAsync(game.Engine))
|
||||
_queue.Add(await _engines.GetImportInfoAsync(game.Engine));
|
||||
|
||||
foreach (var genre in game.Genres)
|
||||
if (!InQueue(genre, _genres) && await _genres.CanImportAsync(genre))
|
||||
_queue.Add(await _genres.GetImportInfoAsync(genre));
|
||||
|
||||
foreach (var multiplayerMode in game.MultiplayerModes)
|
||||
if (!InQueue(multiplayerMode, _multiplayerModes) && await _multiplayerModes.CanImportAsync(multiplayerMode))
|
||||
_queue.Add(await _multiplayerModes.GetImportInfoAsync(multiplayerMode));
|
||||
|
||||
foreach (var platform in game.Platforms)
|
||||
if (!InQueue(platform, _platforms) && await _platforms.CanImportAsync(platform))
|
||||
_queue.Add(await _platforms.GetImportInfoAsync(platform));
|
||||
|
||||
foreach (var publisher in game.Publishers)
|
||||
if (!InQueue(publisher, _publishers) && await _publishers.CanImportAsync(publisher))
|
||||
_queue.Add(await _publishers.GetImportInfoAsync(publisher));
|
||||
|
||||
foreach (var tag in game.Tags)
|
||||
if (!InQueue(tag, _tags) && await _tags.CanImportAsync(tag))
|
||||
_queue.Add(await _tags.GetImportInfoAsync(tag));
|
||||
|
||||
if (!InQueue(game, _games) && await _games.CanImportAsync(game))
|
||||
_queue.Add(await _games.GetImportInfoAsync(game));
|
||||
}
|
||||
|
||||
private bool InQueue<TRecord, TEntity>(TRecord record, BaseImporter<TRecord, TEntity> importer)
|
||||
where TRecord : class =>
|
||||
_queue.Any(qi => qi.Key == importer.GetKey(record));
|
||||
|
||||
public async Task ImportQueueAsync()
|
||||
{
|
||||
OnImportStarted?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
// Import metadata before games
|
||||
_queue = _queue
|
||||
.OrderBy(qi => qi.Type == nameof(Game))
|
||||
.ThenBy(qi => qi.Type)
|
||||
.ThenBy(qi => qi.Name)
|
||||
.ToList();
|
||||
|
||||
foreach (var queueItem in _queue)
|
||||
{
|
||||
CurrentItem = queueItem;
|
||||
|
||||
OnImportProgress?.Invoke(this, new ImportStatusUpdate
|
||||
{
|
||||
CurrentItem = CurrentItem,
|
||||
Index = Processed,
|
||||
Total = Total,
|
||||
});
|
||||
|
||||
switch (queueItem.Type)
|
||||
{
|
||||
case nameof(Collection):
|
||||
await _collections.ImportAsync(queueItem);
|
||||
break;
|
||||
|
||||
case "Developer":
|
||||
await _developers.ImportAsync(queueItem);
|
||||
break;
|
||||
|
||||
case nameof(Engine):
|
||||
await _engines.ImportAsync(queueItem);
|
||||
break;
|
||||
|
||||
case nameof(Game):
|
||||
await _games.ImportAsync(queueItem);
|
||||
break;
|
||||
|
||||
case nameof(Genre):
|
||||
await _genres.ImportAsync(queueItem);
|
||||
break;
|
||||
|
||||
case nameof(MultiplayerMode):
|
||||
await _multiplayerModes.ImportAsync(queueItem);
|
||||
break;
|
||||
|
||||
case nameof(Platform):
|
||||
await _platforms.ImportAsync(queueItem);
|
||||
break;
|
||||
|
||||
case "Publisher":
|
||||
await _publishers.ImportAsync(queueItem);
|
||||
break;
|
||||
|
||||
case nameof(Tag):
|
||||
await _tags.ImportAsync(queueItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OnImportCompleted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
10
LANCommander.Launcher.Services/Import/ImportItemInfo.cs
Normal file
10
LANCommander.Launcher.Services/Import/ImportItemInfo.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
namespace LANCommander.Launcher.Services.Import;
|
||||
|
||||
public class ImportItemInfo<T> : IImportItemInfo where T : class
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool Processed { get; set; }
|
||||
public T Record { get; set; }
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
namespace LANCommander.Launcher.Models;
|
||||
namespace LANCommander.Launcher.Services.Import;
|
||||
|
||||
public class ImportStatusUpdate
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public int Total { get; set; }
|
||||
public ImportItem CurrentItem { get; set; }
|
||||
public IImportItemInfo CurrentItem { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public abstract class BaseImporter<TRecord, TEntity> : IImporter<TRecord, TEntity> where TRecord : class
|
||||
{
|
||||
protected ImportContext ImportContext { get; private set; }
|
||||
|
||||
public void UseContext(ImportContext importContext)
|
||||
{
|
||||
ImportContext = importContext;
|
||||
}
|
||||
|
||||
public async Task<TEntity> ImportAsync(IImportItemInfo importItem)
|
||||
{
|
||||
if (importItem is ImportItemInfo<TRecord> importItemInfo)
|
||||
{
|
||||
if (await ExistsAsync(importItemInfo.Record))
|
||||
{
|
||||
importItem.Processed = true;
|
||||
return await UpdateAsync(importItemInfo.Record);
|
||||
}
|
||||
|
||||
importItem.Processed = true;
|
||||
return await AddAsync(importItemInfo.Record);
|
||||
}
|
||||
|
||||
throw new ImportSkippedException<TRecord>(null, "Import item record is not supported by this importer.");
|
||||
}
|
||||
|
||||
public abstract string GetKey(TRecord record);
|
||||
public abstract Task<ImportItemInfo<TRecord>> GetImportInfoAsync(TRecord record);
|
||||
public abstract Task<bool> CanImportAsync(TRecord record);
|
||||
public abstract Task<TEntity> AddAsync(TRecord record);
|
||||
public abstract Task<TEntity> UpdateAsync(TRecord record);
|
||||
public abstract Task<bool> ExistsAsync(TRecord record);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class CollectionImporter(
|
||||
CollectionService collectionService,
|
||||
ILogger<CollectionImporter> logger) : BaseImporter<Collection, Data.Models.Collection>
|
||||
{
|
||||
public override async Task<ImportItemInfo<Collection>> GetImportInfoAsync(Collection record)
|
||||
{
|
||||
return new ImportItemInfo<Collection>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = record.Name,
|
||||
Type = nameof(Collection),
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(Collection record) => $"{nameof(Collection)}/{record.Name}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(Collection record)
|
||||
{
|
||||
var existing = await collectionService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Collection> AddAsync(Collection record)
|
||||
{
|
||||
var collection = new Data.Models.Collection
|
||||
{
|
||||
Name = record.Name,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await collectionService.AddAsync(collection);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Collection>(record, "An unknown error occurred while trying to add collection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Collection> UpdateAsync(Collection record)
|
||||
{
|
||||
var existing = await collectionService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Name = record.Name;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.UpdatedOn = record.UpdatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Collection>(record, "An unknown error occurred while trying to update collection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(Collection record) => await collectionService.ExistsAsync(c => c.Name == record.Name);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class DeveloperImporter(
|
||||
CompanyService companyService,
|
||||
ILogger<DeveloperImporter> logger) : BaseImporter<Company, Data.Models.Company>
|
||||
{
|
||||
public override async Task<ImportItemInfo<Company>> GetImportInfoAsync(Company record)
|
||||
{
|
||||
return new ImportItemInfo<Company>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = record.Name,
|
||||
Type = "Developer",
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(Company record) => $"{nameof(Company)}/{record.Name}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(Company record)
|
||||
{
|
||||
var existing = await companyService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Company> AddAsync(Company record)
|
||||
{
|
||||
var company = new Data.Models.Company
|
||||
{
|
||||
Name = record.Name,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await companyService.AddAsync(company);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Company>(record, "An unknown error occurred while trying to add company", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Company> UpdateAsync(Company record)
|
||||
{
|
||||
var existing = await companyService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Name = record.Name;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.UpdatedOn = record.UpdatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Company>(record, "An unknown error occurred while trying to update company", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(Company record) => await companyService.ExistsAsync(c => c.Name == record.Name);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class EngineImporter(
|
||||
EngineService engineService,
|
||||
ILogger<EngineImporter> logger) : BaseImporter<Engine, Data.Models.Engine>
|
||||
{
|
||||
public override async Task<ImportItemInfo<Engine>> GetImportInfoAsync(Engine record)
|
||||
{
|
||||
return new ImportItemInfo<Engine>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = record.Name,
|
||||
Type = nameof(Engine),
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(Engine record) => $"{nameof(Engine)}/{record.Name}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(Engine record)
|
||||
{
|
||||
var existing = await engineService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Engine> AddAsync(Engine record)
|
||||
{
|
||||
var engine = new Data.Models.Engine
|
||||
{
|
||||
Name = record.Name,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await engineService.AddAsync(engine);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Engine>(record, "An unknown error occurred while trying to add engine", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Engine> UpdateAsync(Engine record)
|
||||
{
|
||||
var existing = await engineService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Name = record.Name;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.UpdatedOn = record.UpdatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Engine>(record, "An unknown error occurred while trying to update engine", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(Engine record) => await engineService.ExistsAsync(c => c.Name == record.Name);
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class GameImporter(
|
||||
GameService gameService,
|
||||
ILogger<GameImporter> logger) : BaseImporter<Game, Data.Models.Game>
|
||||
{
|
||||
public override async Task<ImportItemInfo<Game>> GetImportInfoAsync(Game record)
|
||||
{
|
||||
return new ImportItemInfo<Game>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = record.Title,
|
||||
Type = nameof(Game),
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(Game record) => $"{nameof(Game)}/{record.Id}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(Game record)
|
||||
{
|
||||
var existing = await gameService.GetAsync(record.Id);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Game> AddAsync(Game record)
|
||||
{
|
||||
var game = new Data.Models.Game
|
||||
{
|
||||
Title = record.Title,
|
||||
SortTitle = record.SortTitle,
|
||||
Description = record.Description,
|
||||
Notes = record.Notes,
|
||||
ReleasedOn = record.ReleasedOn,
|
||||
Singleplayer = record.Singleplayer,
|
||||
Type = record.Type,
|
||||
IGDBId = record.IGDBId,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await gameService.AddAsync(game);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Game>(record, "An unknown error occurred while trying to add game", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Game> UpdateAsync(Game record)
|
||||
{
|
||||
var existing = await gameService.GetAsync(record.Id);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Title = record.Title;
|
||||
existing.SortTitle = record.SortTitle;
|
||||
existing.Description = record.Description;
|
||||
existing.Notes = record.Notes;
|
||||
existing.ReleasedOn = record.ReleasedOn;
|
||||
existing.Singleplayer = record.Singleplayer;
|
||||
existing.Type = record.Type;
|
||||
existing.IGDBId = record.IGDBId;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Game>(record, "An unknown error occurred while trying to update game", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(Game record) => await gameService.ExistsAsync(record.Id);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class GenreImporter(
|
||||
GenreService genreService,
|
||||
ILogger<GenreImporter> logger) : BaseImporter<Genre, Data.Models.Genre>
|
||||
{
|
||||
public override async Task<ImportItemInfo<Genre>> GetImportInfoAsync(Genre record)
|
||||
{
|
||||
return new ImportItemInfo<Genre>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = record.Name,
|
||||
Type = nameof(Genre),
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(Genre record) => $"{nameof(Genre)}/{record.Name}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(Genre record)
|
||||
{
|
||||
var existing = await genreService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Genre> AddAsync(Genre record)
|
||||
{
|
||||
var genre = new Data.Models.Genre
|
||||
{
|
||||
Name = record.Name,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await genreService.AddAsync(genre);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Genre>(record, "An unknown error occurred while trying to add genre", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Genre> UpdateAsync(Genre record)
|
||||
{
|
||||
var existing = await genreService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Name = record.Name;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.UpdatedOn = record.UpdatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Genre>(record, "An unknown error occurred while trying to update genre", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(Genre record) => await genreService.ExistsAsync(c => c.Name == record.Name);
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class MultiplayerModeImporter(
|
||||
MultiplayerModeService multiplayerModeService,
|
||||
ILogger<MultiplayerModeImporter> logger) : BaseImporter<MultiplayerMode, Data.Models.MultiplayerMode>
|
||||
{
|
||||
public override async Task<ImportItemInfo<MultiplayerMode>> GetImportInfoAsync(MultiplayerMode record)
|
||||
{
|
||||
return new ImportItemInfo<MultiplayerMode>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = $"{record.NetworkProtocol} - {record.Type}",
|
||||
Type = nameof(MultiplayerMode),
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(MultiplayerMode record) => $"{nameof(Collection)}/{record.NetworkProtocol}:{record.Type}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(MultiplayerMode record)
|
||||
{
|
||||
var existing = await multiplayerModeService.FirstOrDefaultAsync(mm => mm.Type == record.Type && mm.NetworkProtocol == record.NetworkProtocol);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.MultiplayerMode> AddAsync(MultiplayerMode record)
|
||||
{
|
||||
var multiplayerMode = new Data.Models.MultiplayerMode
|
||||
{
|
||||
Type = record.Type,
|
||||
Description = record.Description,
|
||||
MaxPlayers = record.MaxPlayers,
|
||||
MinPlayers = record.MinPlayers,
|
||||
NetworkProtocol = record.NetworkProtocol,
|
||||
Spectators = record.Spectators,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await multiplayerModeService.AddAsync(multiplayerMode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<MultiplayerMode>(record, "An unknown error occurred while trying to add multiplayer mode", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.MultiplayerMode> UpdateAsync(MultiplayerMode record)
|
||||
{
|
||||
var existing = await multiplayerModeService.FirstOrDefaultAsync(mm => mm.Type == record.Type && mm.NetworkProtocol == record.NetworkProtocol);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Type = record.Type;
|
||||
existing.Description = record.Description;
|
||||
existing.MaxPlayers = record.MaxPlayers;
|
||||
existing.MinPlayers = record.MinPlayers;
|
||||
existing.NetworkProtocol = record.NetworkProtocol;
|
||||
existing.Spectators = record.Spectators;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.UpdatedOn = record.UpdatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<MultiplayerMode>(record, "An unknown error occurred while trying to update multiplayer mode", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(MultiplayerMode record) => await multiplayerModeService.ExistsAsync(mm => mm.Type == record.Type && mm.NetworkProtocol == record.NetworkProtocol);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class PlatformImporter(
|
||||
PlatformService platformService,
|
||||
ILogger<PlatformImporter> logger) : BaseImporter<Platform, Data.Models.Platform>
|
||||
{
|
||||
public override async Task<ImportItemInfo<Platform>> GetImportInfoAsync(Platform record)
|
||||
{
|
||||
return new ImportItemInfo<Platform>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = record.Name,
|
||||
Type = nameof(Platform),
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(Platform record) => $"{nameof(Platform)}/{record.Name}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(Platform record)
|
||||
{
|
||||
var existing = await platformService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Platform> AddAsync(Platform record)
|
||||
{
|
||||
var platform = new Data.Models.Platform
|
||||
{
|
||||
Name = record.Name,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await platformService.AddAsync(platform);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Platform>(record, "An unknown error occurred while trying to add platform", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Platform> UpdateAsync(Platform record)
|
||||
{
|
||||
var existing = await platformService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Name = record.Name;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.UpdatedOn = record.UpdatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Platform>(record, "An unknown error occurred while trying to update platform", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(Platform record) => await platformService.ExistsAsync(c => c.Name == record.Name);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class PublisherImporter(
|
||||
CompanyService companyService,
|
||||
ILogger<PublisherImporter> logger) : BaseImporter<Company, Data.Models.Company>
|
||||
{
|
||||
public override async Task<ImportItemInfo<Company>> GetImportInfoAsync(Company record)
|
||||
{
|
||||
return new ImportItemInfo<Company>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = record.Name,
|
||||
Type = "Publisher",
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(Company record) => $"{nameof(Company)}/{record.Name}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(Company record)
|
||||
{
|
||||
var existing = await companyService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Company> AddAsync(Company record)
|
||||
{
|
||||
var company = new Data.Models.Company
|
||||
{
|
||||
Name = record.Name,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await companyService.AddAsync(company);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Company>(record, "An unknown error occurred while trying to add company", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Company> UpdateAsync(Company record)
|
||||
{
|
||||
var existing = await companyService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Name = record.Name;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.UpdatedOn = record.UpdatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Company>(record, "An unknown error occurred while trying to update company", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(Company record) => await companyService.ExistsAsync(c => c.Name == record.Name);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using LANCommander.Launcher.Services.Exceptions;
|
||||
using LANCommander.SDK.Models.Manifest;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace LANCommander.Launcher.Services.Import.Importers;
|
||||
|
||||
public class TagImporter(
|
||||
TagService tagService,
|
||||
ILogger<TagImporter> logger) : BaseImporter<Tag, Data.Models.Tag>
|
||||
{
|
||||
public override async Task<ImportItemInfo<Tag>> GetImportInfoAsync(Tag record)
|
||||
{
|
||||
return new ImportItemInfo<Tag>
|
||||
{
|
||||
Key = GetKey(record),
|
||||
Name = record.Name,
|
||||
Type = nameof(Tag),
|
||||
Record = record,
|
||||
};
|
||||
}
|
||||
|
||||
public override string GetKey(Tag record) => $"{nameof(Tag)}/{record.Name}";
|
||||
|
||||
public override async Task<bool> CanImportAsync(Tag record)
|
||||
{
|
||||
var existing = await tagService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
if (existing == null)
|
||||
return true;
|
||||
|
||||
return record.UpdatedOn > existing.ImportedOn;
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Tag> AddAsync(Tag record)
|
||||
{
|
||||
var tag = new Data.Models.Tag
|
||||
{
|
||||
Name = record.Name,
|
||||
CreatedOn = record.CreatedOn,
|
||||
UpdatedOn = record.UpdatedOn,
|
||||
ImportedOn = DateTime.UtcNow
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return await tagService.AddAsync(tag);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Tag>(record, "An unknown error occurred while trying to add tag", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<Data.Models.Tag> UpdateAsync(Tag record)
|
||||
{
|
||||
var existing = await tagService.FirstOrDefaultAsync(c => c.Name == record.Name);
|
||||
|
||||
try
|
||||
{
|
||||
existing.Name = record.Name;
|
||||
existing.CreatedOn = record.CreatedOn;
|
||||
existing.UpdatedOn = record.UpdatedOn;
|
||||
existing.ImportedOn = DateTime.UtcNow;
|
||||
|
||||
return existing;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ImportSkippedException<Tag>(record, "An unknown error occurred while trying to update tag", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(Tag record) => await tagService.ExistsAsync(c => c.Name == record.Name);
|
||||
}
|
||||
|
|
@ -1,48 +1,31 @@
|
|||
using LANCommander.Launcher.Data;
|
||||
using LANCommander.Launcher.Models;
|
||||
using LANCommander.SDK.Extensions;
|
||||
using LANCommander.SDK.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using LANCommander.Launcher.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using LANCommander.Launcher.Services.Extensions;
|
||||
using LANCommander.SDK;
|
||||
using LANCommander.SDK.Models;
|
||||
using BaseModel = LANCommander.Launcher.Data.Models.BaseModel;
|
||||
using LANCommander.Launcher.Services.Import;
|
||||
using LANCommander.Launcher.Services.Import.Factories;
|
||||
using LANCommander.SDK.Services;
|
||||
using Collection = LANCommander.Launcher.Data.Models.Collection;
|
||||
using Company = LANCommander.Launcher.Data.Models.Company;
|
||||
using Engine = LANCommander.Launcher.Data.Models.Engine;
|
||||
using Game = LANCommander.Launcher.Data.Models.Game;
|
||||
using Genre = LANCommander.Launcher.Data.Models.Genre;
|
||||
using Media = LANCommander.Launcher.Data.Models.Media;
|
||||
using MultiplayerMode = LANCommander.Launcher.Data.Models.MultiplayerMode;
|
||||
using Platform = LANCommander.Launcher.Data.Models.Platform;
|
||||
using PlaySession = LANCommander.Launcher.Data.Models.PlaySession;
|
||||
using Settings = LANCommander.Launcher.Settings.Settings;
|
||||
using Tag = LANCommander.Launcher.Data.Models.Tag;
|
||||
|
||||
namespace LANCommander.Launcher.Services
|
||||
{
|
||||
public class ImportService(
|
||||
ILogger<ImportService> logger,
|
||||
DatabaseContext databaseContext,
|
||||
LibraryService libraryService,
|
||||
MediaService mediaService,
|
||||
EngineService engineService,
|
||||
GameService gameService,
|
||||
MessageBusService messageBusService,
|
||||
SDK.Client client) : BaseService(logger)
|
||||
ImportContextFactory importContextFactory,
|
||||
GameClient gameClient,
|
||||
LibraryClient libraryClient) : BaseService(logger)
|
||||
{
|
||||
private ImportProgress _importProgress = new();
|
||||
public ImportProgress Progress => _importProgress;
|
||||
|
||||
public delegate Task OnImportUpdatedHandler(ImportStatusUpdate update);
|
||||
public event OnImportUpdatedHandler OnImportUpdated;
|
||||
|
||||
public delegate Task OnImportCompleteHandler();
|
||||
public event OnImportCompleteHandler OnImportComplete;
|
||||
|
||||
public delegate Task OnImportFailedHandler(Exception ex);
|
||||
public event OnImportFailedHandler OnImportFailed;
|
||||
public EventHandler OnImportStarted;
|
||||
public EventHandler<ImportStatusUpdate> OnImportStatusUpdate;
|
||||
public EventHandler OnImportComplete;
|
||||
public EventHandler<Exception> OnImportError;
|
||||
|
||||
private IEnumerable<Collection> Collections;
|
||||
private IEnumerable<Company> Companies;
|
||||
|
|
@ -52,633 +35,45 @@ namespace LANCommander.Launcher.Services
|
|||
private IEnumerable<Tag> Tags;
|
||||
private IEnumerable<MultiplayerMode> MultiplayerModes;
|
||||
|
||||
public void ImportHasCompleted()
|
||||
{
|
||||
OnImportComplete?.Invoke();
|
||||
}
|
||||
|
||||
public async Task ImportAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await ImportLibraryAsync();
|
||||
|
||||
OnImportComplete?.Invoke();
|
||||
OnImportComplete?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnImportFailed?.Invoke(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Game> ImportGameAsync(Guid id)
|
||||
{
|
||||
var game = await client.Games.GetAsync(id);
|
||||
|
||||
return await ImportGameAsync(game);
|
||||
}
|
||||
|
||||
public async Task<Game> ImportGameAsync(SDK.Models.Game game)
|
||||
{
|
||||
using (var op = Logger.BeginOperation("Importing game {GameTitle}", game.Title))
|
||||
{
|
||||
try
|
||||
{
|
||||
var existing = false;
|
||||
var localGame = await gameService.GetAsync(game.Id);
|
||||
|
||||
if (localGame == null)
|
||||
localGame = new Game()
|
||||
{
|
||||
Id = game.Id,
|
||||
};
|
||||
else
|
||||
existing = true;
|
||||
|
||||
if (localGame.ImportedOn > game.UpdatedOn)
|
||||
{
|
||||
Logger.LogInformation($"Skipping {game.Title}, no new information to grab");
|
||||
return localGame;
|
||||
}
|
||||
|
||||
localGame.Title = game.Title;
|
||||
localGame.SortTitle = String.IsNullOrWhiteSpace(game.SortTitle) ? String.Empty : game.SortTitle;
|
||||
localGame.Description = String.IsNullOrWhiteSpace(game.Description) ? String.Empty : game.Description;
|
||||
localGame.Notes = String.IsNullOrWhiteSpace(game.Notes) ? String.Empty : game.Notes;
|
||||
localGame.ReleasedOn = game.ReleasedOn;
|
||||
localGame.ImportedOn = DateTime.UtcNow;
|
||||
localGame.Type = (Data.Enums.GameType)(int)game.Type;
|
||||
localGame.Singleplayer = game.Singleplayer;
|
||||
|
||||
if (!existing)
|
||||
localGame = await gameService.AddAsync(localGame);
|
||||
|
||||
if (game.BaseGameId != Guid.Empty && localGame.BaseGameId != game.BaseGameId)
|
||||
{
|
||||
var baseGame = await gameService.GetAsync(game.BaseGameId);
|
||||
|
||||
if (baseGame == null)
|
||||
{
|
||||
await ImportGameAsync(game.BaseGameId);
|
||||
|
||||
localGame.BaseGame = await gameService.GetAsync(game.BaseGameId);
|
||||
}
|
||||
else
|
||||
{
|
||||
localGame.BaseGame = baseGame;
|
||||
}
|
||||
}
|
||||
|
||||
var childGamesIds = game.DependentGames.ToArray();
|
||||
foreach (var childGameId in childGamesIds)
|
||||
{
|
||||
await ImportGameAsync(childGameId);
|
||||
}
|
||||
|
||||
#region Update Game Engine
|
||||
|
||||
if (game.Engine == null && localGame.Engine != null)
|
||||
{
|
||||
localGame.Engine = null;
|
||||
localGame.EngineId = null;
|
||||
}
|
||||
else if (game.Engine != null)
|
||||
{
|
||||
var engine = await engineService.GetAsync(game.Engine.Id);
|
||||
|
||||
if (engine != null)
|
||||
{
|
||||
localGame.Engine = engine;
|
||||
localGame.EngineId = engine.Id;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
await databaseContext.BulkImport<Collection, SDK.Models.Collection>()
|
||||
.SetTarget(localGame.Collections)
|
||||
.UseSource(game.Collections)
|
||||
.AsBatch()
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Name = s.Name;
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
// Check if the relationship already exists
|
||||
var linked = databaseContext.Entry(t)
|
||||
.Collection(x => x.Games)
|
||||
.Query()
|
||||
.Any(g => g.Id == localGame.Id);
|
||||
|
||||
if (!linked)
|
||||
t.Games.Add(localGame);
|
||||
})
|
||||
.ImportAsync();
|
||||
|
||||
await databaseContext.BulkImport<Genre, SDK.Models.Genre>()
|
||||
.SetTarget(localGame.Genres)
|
||||
.UseSource(game.Genres)
|
||||
.AsBatch()
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Name = s.Name;
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
// Check if the relationship already exists
|
||||
var linked = databaseContext.Entry(t)
|
||||
.Collection(x => x.Games)
|
||||
.Query()
|
||||
.Any(g => g.Id == localGame.Id);
|
||||
|
||||
if (!linked)
|
||||
t.Games.Add(localGame);
|
||||
})
|
||||
.ImportAsync();
|
||||
|
||||
await databaseContext.BulkImport<Company, SDK.Models.Company>()
|
||||
.SetTarget(localGame.Publishers)
|
||||
.UseSource(game.Publishers)
|
||||
.AsBatch()
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Name = s.Name;
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
// Check if the relationship already exists
|
||||
var linked = databaseContext.Entry(t)
|
||||
.Collection(x => x.PublishedGames)
|
||||
.Query()
|
||||
.Any(g => g.Id == localGame.Id);
|
||||
|
||||
if (!linked)
|
||||
t.PublishedGames.Add(localGame);
|
||||
})
|
||||
.ImportAsync();
|
||||
|
||||
await databaseContext.BulkImport<Company, SDK.Models.Company>()
|
||||
.SetTarget(localGame.Developers)
|
||||
.UseSource(game.Developers)
|
||||
.AsBatch()
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Name = s.Name;
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
// Check if the relationship already exists
|
||||
var linked = databaseContext.Entry(t)
|
||||
.Collection(x => x.DevelopedGames)
|
||||
.Query()
|
||||
.Any(g => g.Id == localGame.Id);
|
||||
|
||||
if (!linked)
|
||||
t.DevelopedGames.Add(localGame);
|
||||
})
|
||||
.ImportAsync();
|
||||
|
||||
await databaseContext.BulkImport<Tag, SDK.Models.Tag>()
|
||||
.SetTarget(localGame.Tags)
|
||||
.UseSource(game.Tags)
|
||||
.AsBatch()
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Name = s.Name;
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
// Check if the relationship already exists
|
||||
var linked = databaseContext.Entry(t)
|
||||
.Collection(x => x.Games)
|
||||
.Query()
|
||||
.Any(g => g.Id == localGame.Id);
|
||||
|
||||
if (!linked)
|
||||
t.Games.Add(localGame);
|
||||
})
|
||||
.ImportAsync();
|
||||
|
||||
await databaseContext.BulkImport<MultiplayerMode, SDK.Models.MultiplayerMode>()
|
||||
.SetTarget(localGame.MultiplayerModes)
|
||||
.UseSource(game.MultiplayerModes)
|
||||
.AsBatch()
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Game = localGame;
|
||||
t.Description = s.Description;
|
||||
t.MinPlayers = s.MinPlayers;
|
||||
t.MaxPlayers = s.MaxPlayers;
|
||||
t.Spectators = s.Spectators;
|
||||
t.Type = s.Type;
|
||||
t.NetworkProtocol = s.NetworkProtocol;
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
var linked = t.GameId == localGame.Id;
|
||||
|
||||
if (!linked)
|
||||
t.Game = localGame;
|
||||
})
|
||||
.ImportAsync();
|
||||
|
||||
await databaseContext.BulkImport<Platform, SDK.Models.Platform>()
|
||||
.SetTarget(localGame.Platforms)
|
||||
.UseSource(game.Platforms)
|
||||
.AsBatch()
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Name = s.Name;
|
||||
t.Games.Add(localGame);
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
// Check if the relationship already exists
|
||||
var linked = databaseContext.Entry(t)
|
||||
.Collection(x => x.Games)
|
||||
.Query()
|
||||
.Any(g => g.Id == localGame.Id);
|
||||
|
||||
if (!linked)
|
||||
t.Games.Add(localGame);
|
||||
})
|
||||
.ImportAsync();
|
||||
|
||||
/*await databaseContext.BulkImport<PlaySession, SDK.Models.PlaySession>()
|
||||
.SetTarget(localGame.PlaySessions)
|
||||
.UseSource(game.PlaySessions)
|
||||
.Include(p => p.Game)
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Game = localGame;
|
||||
t.Start = s.Start;
|
||||
t.End = s.End;
|
||||
t.UserId = s.UserId;
|
||||
})
|
||||
.AsNoRemove()
|
||||
.ImportAsync();*/
|
||||
|
||||
var importedMedia = await databaseContext.BulkImport<Media, SDK.Models.Media>()
|
||||
.SetTarget(localGame.Media)
|
||||
.UseSource(game.Media)
|
||||
.AsBatch()
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Name = s.Name;
|
||||
t.Crc32 = s.Crc32;
|
||||
t.Type = s.Type;
|
||||
t.FileId = s.FileId;
|
||||
t.MimeType = s.MimeType;
|
||||
t.SourceUrl = s.SourceUrl;
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
var linked = t.GameId == localGame.Id;
|
||||
|
||||
if (!linked)
|
||||
t.Game = localGame;
|
||||
})
|
||||
.AsNoRemove()
|
||||
.ImportAsync();
|
||||
|
||||
foreach (var media in importedMedia)
|
||||
{
|
||||
var localPath = client.Media.GetLocalPath(media.FileId, media.Crc32);
|
||||
|
||||
if (!File.Exists(localPath) && media.Type != SDK.Enums.MediaType.Manual)
|
||||
{
|
||||
await client.Media.DownloadAsync(new SDK.Models.Media
|
||||
{
|
||||
Id = media.Id,
|
||||
FileId = media.FileId
|
||||
}, localPath);
|
||||
|
||||
messageBusService.MediaChanged(media);
|
||||
}
|
||||
}
|
||||
|
||||
#region Check Installation Status
|
||||
|
||||
foreach (var installDirectory in client.Settings.CurrentValue.Games.InstallDirectories)
|
||||
{
|
||||
var gameDirectory = await client.Games.GetInstallDirectory(game, installDirectory);
|
||||
|
||||
if (Directory.Exists(gameDirectory))
|
||||
{
|
||||
var manifestLocation = ManifestHelper.GetPath(gameDirectory, game.Id);
|
||||
|
||||
if (File.Exists(manifestLocation))
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.GameManifest>(gameDirectory, game.Id);
|
||||
|
||||
localGame.Installed = true;
|
||||
localGame.InstalledOn = DateTime.Now;
|
||||
localGame.InstallDirectory = gameDirectory;
|
||||
localGame.InstalledVersion = manifest.Version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
var playSessions = await client.PlaySessions.GetAsync(localGame.Id);
|
||||
|
||||
if (playSessions != null)
|
||||
{
|
||||
await databaseContext.BulkImport<PlaySession, SDK.Models.PlaySession>()
|
||||
.SetTarget(localGame.PlaySessions)
|
||||
.UseSource(playSessions)
|
||||
.Include(p => p.Game)
|
||||
.Assign((t, s) =>
|
||||
{
|
||||
t.Start = s.Start;
|
||||
t.End = s.End;
|
||||
t.UserId = s.UserId;
|
||||
})
|
||||
.AssignRelationships((t, s) =>
|
||||
{
|
||||
// Ensure the game is tracked before checking relationships
|
||||
if (databaseContext.Entry(localGame).State == EntityState.Detached)
|
||||
databaseContext.Attach(localGame);
|
||||
|
||||
var linked = t.GameId == localGame.Id;
|
||||
|
||||
if (!linked)
|
||||
t.Game = localGame;
|
||||
})
|
||||
.AsNoRemove()
|
||||
.ImportAsync();
|
||||
}
|
||||
|
||||
// Save all pending changes from batch operations
|
||||
await databaseContext.SaveChangesAsync();
|
||||
|
||||
localGame = await gameService.UpdateAsync(localGame);
|
||||
|
||||
return localGame;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Could not import game {GameTitle}", game.Title);
|
||||
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
op.Complete();
|
||||
}
|
||||
OnImportError?.Invoke(this, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ImportLibraryAsync()
|
||||
{
|
||||
var remoteLibrary = await client.Library.GetAsync();
|
||||
var remoteLibrary = await libraryClient.GetAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await ImportLibraryAsync(remoteLibrary);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Could not import library!");
|
||||
OnImportFailed?.Invoke(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ImportLibraryAsync(IEnumerable<SDK.Models.EntityReference> games)
|
||||
{
|
||||
Logger?.LogInformation("Starting library import");
|
||||
|
||||
_importProgress.IsImporting = true;
|
||||
_importProgress.Index = 1;
|
||||
_importProgress.Total = games.Count();
|
||||
var importContext = importContextFactory.Create();
|
||||
|
||||
importContext.OnImportProgress += OnImportStatusUpdate;
|
||||
|
||||
foreach (var game in games)
|
||||
foreach (var game in remoteLibrary)
|
||||
{
|
||||
using var transaction = await databaseContext.Database.BeginTransactionAsync();
|
||||
|
||||
try
|
||||
{
|
||||
var remoteGame = await client.Games.GetAsync(game.Id);
|
||||
var manifest = await gameClient.GetManifestAsync(game.Id);
|
||||
|
||||
_importProgress.CurrentItem = new ImportItem(game.Id, game.Name);
|
||||
|
||||
if (OnImportUpdated != null)
|
||||
{
|
||||
await OnImportUpdated.Invoke(new ImportStatusUpdate
|
||||
{
|
||||
Index = _importProgress.Index,
|
||||
Total = _importProgress.Total,
|
||||
CurrentItem = _importProgress.CurrentItem
|
||||
});
|
||||
}
|
||||
|
||||
if (game != null && remoteGame != null)
|
||||
{
|
||||
var importedGame = await ImportGameAsync(remoteGame);
|
||||
|
||||
await libraryService.AddToLibraryAsync(importedGame);
|
||||
}
|
||||
|
||||
await databaseContext.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
await importContext.AddAsync(manifest);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
|
||||
Logger?.LogError(ex, "Could not import game {GameTitle}", game.Name);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_importProgress.Index++;
|
||||
Logger?.LogError(ex, "Could not add game with ID {GameId} to import queue", game.Id);
|
||||
}
|
||||
}
|
||||
|
||||
_importProgress.IsImporting = false;
|
||||
if (OnImportComplete != null)
|
||||
await OnImportComplete.Invoke();
|
||||
|
||||
Logger?.LogInformation("Importing games completed");
|
||||
await importContext.ImportQueueAsync();
|
||||
}
|
||||
|
||||
public async Task ImportGamesAsync(params Guid[] ids)
|
||||
{
|
||||
var games = await client.Library.GetAsync();
|
||||
var toImport = new List<EntityReference>();
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
var libraryGame = games.FirstOrDefault(g => g.Id == id);
|
||||
|
||||
if (libraryGame == null)
|
||||
{
|
||||
Logger?.LogInformation("Game with ID {GameId} not currently in library", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
toImport.Add(libraryGame);
|
||||
}
|
||||
|
||||
await ImportLibraryAsync(toImport);
|
||||
}
|
||||
|
||||
public async Task ImportRedistributables()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public async Task<Media> ImportMediaAsync(Guid importMediaId, Guid? gameId = null)
|
||||
{
|
||||
SDK.Models.Game game = null;
|
||||
|
||||
if (gameId.HasValue)
|
||||
game = await client.Games.GetAsync(gameId.Value);
|
||||
|
||||
var media = await client.Media.GetAsync(importMediaId);
|
||||
|
||||
return await ImportMediaAsync(media, game);
|
||||
}
|
||||
|
||||
public async Task<Media> ImportMediaAsync(SDK.Models.Media importMedia, SDK.Models.Game game = null)
|
||||
{
|
||||
var media = await mediaService.GetAsync(importMedia.Id);
|
||||
|
||||
if (media == null)
|
||||
media = new Media();
|
||||
|
||||
media.FileId = importMedia.FileId;
|
||||
media.Type = importMedia.Type;
|
||||
media.SourceUrl = importMedia.SourceUrl;
|
||||
media.MimeType = importMedia.MimeType;
|
||||
media.Crc32 = importMedia.Crc32;
|
||||
media.Name = importMedia.Name ?? String.Empty;
|
||||
media.GameId = game?.Id ?? Guid.Empty;
|
||||
|
||||
if (media.Id == Guid.Empty)
|
||||
{
|
||||
media.Id = importMedia.Id;
|
||||
|
||||
await mediaService.AddAsync(media);
|
||||
}
|
||||
else
|
||||
await mediaService.UpdateAsync(media);
|
||||
|
||||
var localPath = client.Media.GetLocalPath(media.FileId, media.Crc32);
|
||||
|
||||
if (!File.Exists(localPath) && media.Type != SDK.Enums.MediaType.Manual)
|
||||
{
|
||||
await client.Media.DownloadAsync(new SDK.Models.Media
|
||||
{
|
||||
Id = media.Id,
|
||||
FileId = media.FileId
|
||||
}, localPath);
|
||||
|
||||
messageBusService.MediaChanged(media);
|
||||
}
|
||||
|
||||
return media;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Could use something like automapper, but that's slow.
|
||||
public async Task<IEnumerable<T>> ImportBulk<T, U, V>(IEnumerable<U> importModels, V service, Func<T, U, T> additionalMapping, bool clean = true)
|
||||
where T : BaseModel
|
||||
where U : SDK.Models.KeyedModel
|
||||
where V : BaseDatabaseService<T>
|
||||
{
|
||||
// This could be handled better... DI?
|
||||
var models = await service.GetAsync();
|
||||
|
||||
foreach (var importModel in importModels)
|
||||
{
|
||||
using (var transaction = databaseContext.Database.BeginTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
var model = models.FirstOrDefault(m => m.Id == importModel.Id);
|
||||
|
||||
if (model == null)
|
||||
model = (T)Activator.CreateInstance(typeof(T));
|
||||
|
||||
model = additionalMapping.Invoke(model, importModel);
|
||||
|
||||
if (model.Id == Guid.Empty)
|
||||
{
|
||||
model.Id = importModel.Id;
|
||||
|
||||
model = await service.AddAsync(model);
|
||||
}
|
||||
else
|
||||
model = await service.UpdateAsync(model);
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
transaction.Rollback();
|
||||
|
||||
continue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (clean)
|
||||
{
|
||||
foreach (var model in models.Where(m => !importModels.Any(im => im.Id == m.Id)))
|
||||
{
|
||||
try
|
||||
{
|
||||
await service.DeleteAsync(model);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Too slow?
|
||||
return await service.GetAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using System.Security.Policy;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using LANCommander.Launcher.Settings.Enums;
|
||||
using LANCommander.SDK.Enums;
|
||||
|
||||
namespace LANCommander.Launcher.Models
|
||||
{
|
||||
|
|
@ -114,7 +115,7 @@ namespace LANCommander.Launcher.Models
|
|||
if (SelectedOptions.Installed)
|
||||
items = items.Where(i => (i.DataItem as Game).Installed);
|
||||
|
||||
items = items.Where(i => (i.DataItem as Game).Type.ValueIsIn(Data.Enums.GameType.MainGame, Data.Enums.GameType.StandaloneExpansion, Data.Enums.GameType.StandaloneMod));
|
||||
items = items.Where(i => (i.DataItem as Game).Type.ValueIsIn(GameType.MainGame, GameType.StandaloneExpansion, GameType.StandaloneMod));
|
||||
|
||||
switch (SelectedOptions.SortBy)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public class ElevatedScriptInterceptor : IScriptInterceptor
|
|||
|
||||
if (script.RunAsAdmin && !isElevated)
|
||||
{
|
||||
var manifest = script.Variables.GetValue<GameManifest>("GameManifest");
|
||||
var manifest = script.Variables.GetValue<SDK.Models.Manifest.Game>("GameManifest");
|
||||
|
||||
var options = new RunScriptCommandLineOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,15 +26,18 @@ namespace LANCommander.Launcher.Services
|
|||
return await Context.Set<T>().FindAsync(id);
|
||||
}
|
||||
|
||||
public virtual async Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
return await Context.Set<T>().FirstOrDefaultAsync(predicate);
|
||||
}
|
||||
|
||||
public virtual IQueryable<T> Query(Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
return Context.Set<T>().Where(predicate);
|
||||
}
|
||||
|
||||
public virtual bool Exists(Guid id)
|
||||
{
|
||||
return GetAsync(id) != null;
|
||||
}
|
||||
public virtual async Task<bool> ExistsAsync(Guid id) => await Context.Set<T>().AnyAsync(x => x.Id == id);
|
||||
public virtual async Task<bool> ExistsAsync(Expression<Func<T, bool>> predicate) => await Context.Set<T>().AnyAsync(predicate);
|
||||
|
||||
public virtual async Task<T> AddAsync(T entity)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@
|
|||
@inherits FeedbackComponent<ActionSelectorDialogOptions, Process>
|
||||
@inject GameService GameService
|
||||
|
||||
<AntList DataSource="Options.Actions" TItem="SDK.Models.Action" Class="ant-list-clickable" Size="ListSize.Small">
|
||||
<AntList DataSource="Options.Actions" TItem="SDK.Models.Manifest.Action" Class="ant-list-clickable" Size="ListSize.Small">
|
||||
<ListItem OnClick="() => Run(Options.Game, context)">
|
||||
@context.Name
|
||||
</ListItem>
|
||||
</AntList>
|
||||
|
||||
@code {
|
||||
void Run(Game game, SDK.Models.Action action)
|
||||
void Run(Game game, SDK.Models.Manifest.Action action)
|
||||
{
|
||||
GameService.Run(game, action);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
@using LANCommander.Launcher.Models
|
||||
@using LANCommander.Launcher.Services.Import
|
||||
@implements IDisposable
|
||||
@inject ImportManagerService ImportManagerService
|
||||
@inject ImportService ImportService
|
||||
|
|
@ -29,9 +30,9 @@
|
|||
if (ImportService != null)
|
||||
{
|
||||
// Clear any existing handlers
|
||||
ImportService.OnImportComplete -= OnImportCompleteHandler;
|
||||
ImportService.OnImportFailed -= OnImportFailedHandler;
|
||||
ImportService.OnImportUpdated -= OnImportUpdatedHandler;
|
||||
//ImportService.OnImportComplete -= OnImportCompleteHandler;
|
||||
//ImportService.OnImportFailed -= OnImportFailedHandler;
|
||||
//ImportService.OnImportUpdated -= OnImportUpdatedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,14 +43,14 @@
|
|||
Logger?.LogInformation("Starting import process");
|
||||
|
||||
// Clear any existing handlers
|
||||
ImportService.OnImportComplete -= OnImportCompleteHandler;
|
||||
ImportService.OnImportFailed -= OnImportFailedHandler;
|
||||
ImportService.OnImportUpdated -= OnImportUpdatedHandler;
|
||||
//ImportService.OnImportComplete -= OnImportCompleteHandler;
|
||||
//ImportService.OnImportFailed -= OnImportFailedHandler;
|
||||
//ImportService.OnImportUpdated -= OnImportUpdatedHandler;
|
||||
|
||||
// Add our handlers
|
||||
ImportService.OnImportComplete += OnImportCompleteHandler;
|
||||
ImportService.OnImportFailed += OnImportFailedHandler;
|
||||
ImportService.OnImportUpdated += OnImportUpdatedHandler;
|
||||
//ImportService.OnImportComplete += OnImportCompleteHandler;
|
||||
//ImportService.OnImportFailed += OnImportFailedHandler;
|
||||
//ImportService.OnImportUpdated += OnImportUpdatedHandler;
|
||||
|
||||
// Now start the import process
|
||||
Importing = true;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
@using LANCommander.Launcher.Data.Models
|
||||
@using LANCommander.Launcher.Settings
|
||||
@using LANCommander.SDK
|
||||
@using LANCommander.SDK.Enums
|
||||
@using LANCommander.SDK.Helpers
|
||||
@using LANCommander.SDK.Services
|
||||
@using Microsoft.Extensions.Options
|
||||
|
|
@ -48,7 +49,7 @@
|
|||
@LocalizationService.GetString("ManageSaves")
|
||||
</MenuItem>
|
||||
|
||||
if (Settings.Value.Games.InstallDirectories.Length > 1 || Game.DependentGames.Any(g => g.Type == Data.Enums.GameType.Expansion || g.Type == Data.Enums.GameType.Mod))
|
||||
if (Settings.Value.Games.InstallDirectories.Length > 1 || Game.DependentGames.Any(g => g.Type == GameType.Expansion || g.Type == GameType.Mod))
|
||||
{
|
||||
<MenuItem OnClick="() => Modify()" Disabled="@ConnectionClient.IsOfflineMode()">
|
||||
@LocalizationService.GetString("Modify")
|
||||
|
|
@ -113,18 +114,18 @@ else
|
|||
[Parameter] public bool ShowPrimaryActions { get; set; }
|
||||
|
||||
Data.Models.Game Game { get; set; }
|
||||
IEnumerable<SDK.Models.Action> GameActions { get; set; } = [];
|
||||
IEnumerable<SDK.Models.Manifest.Action> GameActions { get; set; } = [];
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (Model.DataItem is Game game)
|
||||
{
|
||||
Game = game;
|
||||
List<SDK.Models.Action> actions = [];
|
||||
List<SDK.Models.Manifest.Action> actions = [];
|
||||
|
||||
if (Game.Installed)
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(Game.InstallDirectory, Game.Id);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(Game.InstallDirectory, Game.Id);
|
||||
|
||||
if (manifest != null)
|
||||
{
|
||||
|
|
@ -137,7 +138,7 @@ else
|
|||
}
|
||||
}
|
||||
|
||||
async Task Run(Game game, SDK.Models.Action action)
|
||||
async Task Run(Game game, SDK.Models.Manifest.Action action)
|
||||
{
|
||||
var task = GameService.Run(game, action);
|
||||
|
||||
|
|
@ -162,7 +163,7 @@ else
|
|||
|
||||
async Task Install()
|
||||
{
|
||||
if (Settings.Value.Games.InstallDirectories.Length > 1 || (Model.DataItem as Game).DependentGames.Any(g => g.Type == Data.Enums.GameType.Expansion || g.Type == Data.Enums.GameType.Mod))
|
||||
if (Settings.Value.Games.InstallDirectories.Length > 1 || (Model.DataItem as Game).DependentGames.Any(g => g.Type == GameType.Expansion || g.Type == GameType.Mod))
|
||||
{
|
||||
var modalOptions = new ModalOptions()
|
||||
{
|
||||
|
|
@ -221,7 +222,7 @@ else
|
|||
|
||||
async Task Uninstall()
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(Game.InstallDirectory, Game.Id);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(Game.InstallDirectory, Game.Id);
|
||||
|
||||
string message;
|
||||
if (manifest.SavePaths != null && manifest.SavePaths.Any())
|
||||
|
|
@ -254,7 +255,7 @@ else
|
|||
async Task RemoveFromLibrary()
|
||||
{
|
||||
var hasStandaloneDependent = Game.DependentGames?
|
||||
.Where(g => g.Type != Data.Enums.GameType.Expansion && g.Type != Data.Enums.GameType.Mod)
|
||||
.Where(g => g.Type != GameType.Expansion && g.Type != GameType.Mod)
|
||||
.Any(g => LibraryService.IsInLibrary(g.Id)) ?? false;
|
||||
|
||||
if (!hasStandaloneDependent)
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@
|
|||
try {
|
||||
var media = await MediaService.GetAsync(Id);
|
||||
|
||||
if (media == null && (Connected || OfflineMode))
|
||||
media = await ImportService.ImportMediaAsync(Id);
|
||||
//if (media == null && (Connected || OfflineMode))
|
||||
// media = await ImportService.ImportMediaAsync(Id);
|
||||
|
||||
UpdateMediaUrl(media);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
@using LANCommander.Launcher.Data.Models
|
||||
@using LANCommander.Launcher.Models
|
||||
@using System.Diagnostics
|
||||
@using LANCommander.SDK.Helpers
|
||||
@inject SDK.Client Client
|
||||
@using LANCommander.SDK
|
||||
@using LANCommander.SDK.Services
|
||||
@inject GameService GameService
|
||||
@inject LibraryService LibraryService
|
||||
@inject InstallService InstallService
|
||||
@inject GameClient GameClient
|
||||
@inject LobbyClient LobbyClient
|
||||
@inject ModalService ModalService
|
||||
@inject MessageService MessageService
|
||||
@inject MessageBusService MessageBusService
|
||||
@inject LocalizationService LocalizationService
|
||||
|
||||
@if (State == PlayButtonState.Running)
|
||||
|
|
@ -78,11 +78,11 @@ else
|
|||
|
||||
async Task UpdateState()
|
||||
{
|
||||
if (Client.Games.IsRunning(LibraryItem.Key))
|
||||
if (GameClient.IsRunning(LibraryItem.Key))
|
||||
{
|
||||
await ChangeState(PlayButtonState.Running);
|
||||
}
|
||||
else if (State == PlayButtonState.Running && !Client.Games.IsRunning(LibraryItem.Key))
|
||||
else if (State == PlayButtonState.Running && !GameClient.IsRunning(LibraryItem.Key))
|
||||
{
|
||||
await ChangeState(PlayButtonState.Idle);
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ else
|
|||
{
|
||||
var game = LibraryItem.DataItem as Game;
|
||||
|
||||
var actions = await Client.Games.GetActionsAsync(game.InstallDirectory, game.Id);
|
||||
var actions = await GameClient.GetActionsAsync(game.InstallDirectory, game.Id);
|
||||
|
||||
await ChangeState(PlayButtonState.Starting);
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ else
|
|||
return;
|
||||
}
|
||||
|
||||
var primaryActions = actions.Where(a => a.IsPrimaryAction && (LibraryService.IsInstalled(a.GameId) || a.GameId == Guid.Empty));
|
||||
var primaryActions = actions.Where(a => a.IsPrimaryAction && LibraryService.IsInstalled(game.Id));
|
||||
|
||||
if (primaryActions.Count() == 0)
|
||||
{
|
||||
|
|
@ -142,7 +142,7 @@ else
|
|||
WrapClassName = "game-actions-dialog",
|
||||
AfterClose = async () =>
|
||||
{
|
||||
Client.Lobbies.ReleaseSteam();
|
||||
LobbyClient.ReleaseSteam();
|
||||
|
||||
await ChangeState(PlayButtonState.Idle);
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ else
|
|||
{
|
||||
await ChangeState(PlayButtonState.Stopping);
|
||||
|
||||
await Client.Games.Stop(LibraryItem.Key);
|
||||
await GameClient.Stop(LibraryItem.Key);
|
||||
|
||||
await ChangeState(PlayButtonState.Idle);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
@using LANCommander.Launcher.Data.Models
|
||||
@using LANCommander.Launcher.Models
|
||||
@using LANCommander.SDK.Enums
|
||||
@using LANCommander.SDK.Extensions
|
||||
@inherits FeedbackComponent<Models.ListItem, string>
|
||||
@inject LibraryService LibraryService
|
||||
|
|
@ -27,7 +28,7 @@
|
|||
IconSelected="@IconType.Outline.Close"
|
||||
IconUnselected="@IconType.Fill.Pushpin"
|
||||
ButtonPropsSelected="@(new[] { ("Danger", (object)true) })"
|
||||
DisableSelector="g => g.Type == Data.Enums.GameType.Mod || g.Type == Data.Enums.GameType.Expansion"
|
||||
DisableSelector="g => g.Type == GameType.Mod || g.Type == GameType.Expansion"
|
||||
/>
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +52,7 @@
|
|||
Game = (Game)Options.DataItem;
|
||||
DependentGames = Game?.DependentGames.OrderBy(g => g.SortTitle ?? g.Title).ToList() ?? [];
|
||||
|
||||
SelectedDependentGames = DependentGames?.Where(g => g.Type == Data.Enums.GameType.Expansion || g.Type == Data.Enums.GameType.Mod) ?? [];
|
||||
SelectedDependentGames = DependentGames?.Where(g => g.Type == GameType.Expansion || g.Type == GameType.Mod) ?? [];
|
||||
}
|
||||
|
||||
async Task Close()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
@using LANCommander.Launcher.Data.Models
|
||||
@using LANCommander.Launcher.Models
|
||||
@using LANCommander.SDK.Enums
|
||||
@using LANCommander.SDK.Extensions
|
||||
@namespace LANCommander.Launcher.UI.Components
|
||||
@inject LibraryService LibraryService
|
||||
|
|
@ -232,7 +233,7 @@
|
|||
|
||||
await Hide();
|
||||
|
||||
if (Client.Settings.CurrentValue.Games.InstallDirectories.Length > 1 || (game?.DependentGames?.Any(g => g.Type.IsIn(Data.Enums.GameType.Expansion, Data.Enums.GameType.Mod)) ?? false))
|
||||
if (Client.Settings.CurrentValue.Games.InstallDirectories.Length > 1 || (game?.DependentGames?.Any(g => g.Type.IsIn(GameType.Expansion, GameType.Mod)) ?? false))
|
||||
{
|
||||
var modalOptions = new ModalOptions()
|
||||
{
|
||||
|
|
@ -272,7 +273,7 @@
|
|||
|
||||
try
|
||||
{
|
||||
await ImportService.ImportGameAsync(SelectedGame.Id);
|
||||
// await ImportService.ImportGameAsync(SelectedGame.Id);
|
||||
await LibraryService.AddToLibraryAsync(SelectedGame.Id);
|
||||
await LibraryService.RefreshItemsAsync();
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
StateHasChanged();
|
||||
await Task.Yield();
|
||||
|
||||
await ImportService.ImportGameAsync(Item.Key);
|
||||
// await ImportService.ImportGameAsync(Item.Key);
|
||||
await LibraryService.AddToLibraryAsync(Item.Key);
|
||||
await LibraryService.RefreshItemsAsync();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using LANCommander.SDK.Models;
|
||||
|
||||
namespace LANCommander.SDK.Services;
|
||||
|
||||
public class GameInstallationArchiveInfo
|
||||
{
|
||||
public GameManifest Manifest { get; internal set; }
|
||||
public Models.Manifest.Game Manifest { get; internal set; }
|
||||
public List<ArchiveEntry> Entries { get; private set; } = [];
|
||||
public List<SavePathEntry> SavePaths { get; internal set; }
|
||||
}
|
||||
|
|
@ -13,5 +14,5 @@ public class GameInstallationArchiveInfo
|
|||
public class GameInstallationArchiveEntries
|
||||
{
|
||||
public GameInstallationArchiveInfo BaseGame { get; internal set; } = new();
|
||||
public Dictionary<Guid, GameInstallationArchiveInfo> DependentGames { get; private set; } = [];
|
||||
public Dictionary<Guid, GameInstallationArchiveInfo> Addons { get; private set; } = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public class GameInstallationFileListEntry
|
|||
|
||||
public Guid GameId { get; internal set; }
|
||||
|
||||
public GameManifest Manifest { get; internal set; }
|
||||
public Models.Manifest.Game Manifest { get; internal set; }
|
||||
public List<FileEntry> Files { get; private set; } = [];
|
||||
|
||||
public void Merge(GameInstallationFileListEntry otherInfo)
|
||||
|
|
|
|||
|
|
@ -1,56 +0,0 @@
|
|||
using LANCommander.SDK.Enums;
|
||||
using LANCommander.SDK.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace LANCommander.SDK
|
||||
{
|
||||
public class GameManifest : IKeyedModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string SortTitle { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public GameType Type { get; set; }
|
||||
public DateTime ReleasedOn { get; set; }
|
||||
public string Engine { get; set; }
|
||||
public IEnumerable<string> Genre { get; set; }
|
||||
public IEnumerable<string> Tags { get; set; }
|
||||
public IEnumerable<string> Platforms { get; set; }
|
||||
public IEnumerable<string> Publishers { get; set; }
|
||||
public IEnumerable<string> Developers { get; set; }
|
||||
public IEnumerable<string> Collections { get; set; }
|
||||
public string Version { get; set; }
|
||||
public IEnumerable<Models.Action> Actions { get; set; }
|
||||
public bool Singleplayer { get; set; }
|
||||
public MultiplayerInfo LocalMultiplayer { get; set; }
|
||||
public MultiplayerInfo LanMultiplayer { get; set; }
|
||||
public MultiplayerInfo OnlineMultiplayer { get; set; }
|
||||
public IEnumerable<SavePath> SavePaths { get; set; }
|
||||
public IEnumerable<string> Keys { get; set; }
|
||||
public IEnumerable<Script> Scripts { get; set; }
|
||||
public IEnumerable<Media> Media { get; set; }
|
||||
public IEnumerable<Archive> Archives { get; set; }
|
||||
public IEnumerable<GameSave> Saves { get; set; }
|
||||
public IEnumerable<Guid> DependentGames { get; set; }
|
||||
public IEnumerable<Redistributable> Redistributables { get; set; }
|
||||
public IEnumerable<GameCustomField> CustomFields { get; set; }
|
||||
|
||||
public GameManifest() { }
|
||||
}
|
||||
|
||||
public class MultiplayerInfo
|
||||
{
|
||||
public int MinPlayers { get; set; }
|
||||
public int MaxPlayers { get; set; }
|
||||
public string Description { get; set; }
|
||||
public NetworkProtocol NetworkProtocol { get; set; }
|
||||
}
|
||||
|
||||
public class SavePathEntry
|
||||
{
|
||||
public string ArchivePath { get; set; }
|
||||
public string ActualPath { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -4,12 +4,13 @@ using LANCommander.SDK.Enums;
|
|||
|
||||
namespace LANCommander.SDK.Models.Manifest
|
||||
{
|
||||
public class Game : BaseModel
|
||||
public class Game : BaseModel, IKeyedModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public long? IGDBId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string SortTitle { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string DirectoryName { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||
|
||||
namespace LANCommander.SDK.Models.Manifest
|
||||
{
|
||||
public class Redistributable : BaseModel
|
||||
public class Redistributable : BaseModel, IKeyedModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using LANCommander.SDK.Enums;
|
|||
|
||||
namespace LANCommander.SDK.Models.Manifest
|
||||
{
|
||||
public class Server : BaseModel
|
||||
public class Server : BaseModel, IKeyedModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
|
|
|
|||
7
LANCommander.SDK/Models/SavePathEntry.cs
Normal file
7
LANCommander.SDK/Models/SavePathEntry.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace LANCommander.SDK.Models;
|
||||
|
||||
public class SavePathEntry
|
||||
{
|
||||
public string ArchivePath { get; set; }
|
||||
public string ActualPath { get; set; }
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ using System.Management.Automation;
|
|||
namespace LANCommander.SDK.PowerShell.Cmdlets
|
||||
{
|
||||
[Cmdlet(VerbsCommon.Get, "GameManifest")]
|
||||
[OutputType(typeof(GameManifest))]
|
||||
[OutputType(typeof(SDK.Models.Manifest.Game))]
|
||||
public class GetGameManifestCmdlet : BaseCmdlet
|
||||
{
|
||||
[Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
|
||||
|
|
@ -17,7 +17,7 @@ namespace LANCommander.SDK.PowerShell.Cmdlets
|
|||
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
WriteObject(ManifestHelper.Read<GameManifest>(Path, Id));
|
||||
WriteObject(ManifestHelper.Read<SDK.Models.Manifest.Game>(Path, Id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace LANCommander.SDK.PowerShell.Cmdlets
|
|||
public string Path { get; set; }
|
||||
|
||||
[Parameter(Mandatory = true, Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
|
||||
public GameManifest Manifest { get; set; }
|
||||
public SDK.Models.Manifest.Game Manifest { get; set; }
|
||||
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -148,9 +148,9 @@ namespace LANCommander.SDK
|
|||
}
|
||||
}
|
||||
|
||||
public async Task ExecuteGameActionAsync(string installDirectory, Guid gameId, Models.Action action, string args = "", CancellationToken cancellationToken = default)
|
||||
public async Task ExecuteGameActionAsync(string installDirectory, Guid gameId, Models.Manifest.Action action, string args = "", CancellationToken cancellationToken = default)
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<Models.Manifest.Game>(installDirectory, gameId);
|
||||
|
||||
if (action == null)
|
||||
action = manifest.Actions.FirstOrDefault(a => a.IsPrimaryAction);
|
||||
|
|
|
|||
|
|
@ -112,43 +112,43 @@ namespace LANCommander.SDK.Services
|
|||
.GetAsync<Game>();
|
||||
}
|
||||
|
||||
public async Task<GameManifest> GetManifestAsync(Guid id)
|
||||
public async Task<Models.Manifest.Game> GetManifestAsync(Guid id)
|
||||
{
|
||||
return await apiRequestFactory
|
||||
.Create()
|
||||
.UseAuthenticationToken()
|
||||
.UseVersioning()
|
||||
.UseRoute($"/api/Games/{id}/Manifest")
|
||||
.GetAsync<GameManifest>();
|
||||
.GetAsync<Models.Manifest.Game>();
|
||||
}
|
||||
|
||||
public async Task<ICollection<GameManifest>> GetManifestsAsync(string installDirectory, Guid id)
|
||||
public async Task<ICollection<Models.Manifest.Game>> GetManifestsAsync(string installDirectory, Guid id)
|
||||
{
|
||||
var manifests = new List<GameManifest>();
|
||||
var mainManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, id);
|
||||
var manifests = new List<Models.Manifest.Game>();
|
||||
var mainManifest = await ManifestHelper.ReadAsync<Models.Manifest.Game>(installDirectory, id);
|
||||
|
||||
if (mainManifest == null)
|
||||
return manifests;
|
||||
|
||||
manifests.Add(mainManifest);
|
||||
|
||||
if (mainManifest.DependentGames != null)
|
||||
if (mainManifest.Addons != null)
|
||||
{
|
||||
foreach (var dependentGameId in mainManifest.DependentGames)
|
||||
foreach (var addon in mainManifest.Addons)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ManifestHelper.Exists(installDirectory, dependentGameId))
|
||||
if (ManifestHelper.Exists(installDirectory, addon.Id))
|
||||
{
|
||||
var dependentGameManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, dependentGameId);
|
||||
var addonManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, addon.Id);
|
||||
|
||||
if (dependentGameManifest?.Type == GameType.Expansion || dependentGameManifest?.Type == GameType.Mod)
|
||||
manifests.Add(dependentGameManifest);
|
||||
if (addonManifest?.Type == GameType.Expansion || addonManifest?.Type == GameType.Mod)
|
||||
manifests.Add(addon);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger?.LogError(ex, $"Could not load manifest from dependent game {dependentGameId}");
|
||||
logger?.LogError(ex, $"Could not load manifest from dependent game {addon.Id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,9 +156,9 @@ namespace LANCommander.SDK.Services
|
|||
return manifests;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Models.Action>> GetActionsAsync(string installDirectory, Guid id)
|
||||
public async Task<IEnumerable<Models.Manifest.Action>> GetActionsAsync(string installDirectory, Guid id)
|
||||
{
|
||||
var actions = new List<Models.Action>();
|
||||
var actions = new List<Models.Manifest.Action>();
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -170,7 +170,7 @@ namespace LANCommander.SDK.Services
|
|||
.UseRoute($"/api/Games/{id}/Actions")
|
||||
.UseAuthenticationToken()
|
||||
.UseVersioning()
|
||||
.GetAsync<IEnumerable<Models.Action>>()
|
||||
.GetAsync<IEnumerable<Models.Manifest.Action>>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +190,8 @@ namespace LANCommander.SDK.Services
|
|||
.ThenBy(a => a.SortOrder)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (manifests.Any(m => m.OnlineMultiplayer != null && m.OnlineMultiplayer.NetworkProtocol == NetworkProtocol.Lobby || m.LanMultiplayer != null && m.LanMultiplayer.NetworkProtocol == NetworkProtocol.Lobby))
|
||||
{
|
||||
var primaryAction = actions.Where(a => a.IsPrimaryAction).First();
|
||||
|
|
@ -220,6 +221,7 @@ namespace LANCommander.SDK.Services
|
|||
logger?.LogError(ex, "Could not get lobbies");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
|
@ -387,7 +389,7 @@ namespace LANCommander.SDK.Services
|
|||
{
|
||||
var installResult = new InstallResult(installDirectory, gameId);
|
||||
var gameFileList = installResult.FileList;
|
||||
GameManifest manifest = null;
|
||||
SDK.Models.Manifest.Game manifest = null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(installDirectory))
|
||||
installDirectory = settingsProvider.CurrentValue.Games.InstallDirectories.First();
|
||||
|
|
@ -422,7 +424,7 @@ namespace LANCommander.SDK.Services
|
|||
try
|
||||
{
|
||||
if (ManifestHelper.Exists(destination, game.Id))
|
||||
manifest = await ManifestHelper.ReadAsync<GameManifest>(destination, game.Id);
|
||||
manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(destination, game.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -638,7 +640,7 @@ namespace LANCommander.SDK.Services
|
|||
var installResult = new InstallResult(installDirectory, gameId);
|
||||
var gameFileList = installResult.FileList;
|
||||
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
if (manifest == null)
|
||||
{
|
||||
logger?.LogInformation("Unable to read or find manifest for game with ID {GameId}. Skip uninstallation!", gameId);
|
||||
|
|
@ -649,16 +651,16 @@ namespace LANCommander.SDK.Services
|
|||
gameFileList.BaseGame.Manifest = manifest;
|
||||
var baseFileList = gameFileList.BaseGame;
|
||||
|
||||
#region Uninstall Dependent Games
|
||||
if (manifest.DependentGames != null)
|
||||
#region Uninstall Addons
|
||||
if (manifest.Addons != null)
|
||||
{
|
||||
foreach (var dependentGame in manifest.DependentGames)
|
||||
foreach (var addon in manifest.Addons)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ManifestHelper.Exists(installDirectory, dependentGame))
|
||||
if (ManifestHelper.Exists(installDirectory, addon.Id))
|
||||
{
|
||||
var dependentResult = await UninstallAsync(installDirectory, dependentGame);
|
||||
var dependentResult = await UninstallAsync(installDirectory, addon.Id);
|
||||
gameFileList.MergeDependentGames(dependentResult.FileList);
|
||||
}
|
||||
}
|
||||
|
|
@ -736,7 +738,7 @@ namespace LANCommander.SDK.Services
|
|||
var installResult = new InstallResult(installDirectory, baseGameId);
|
||||
var gameFileList = installResult.FileList;
|
||||
|
||||
var baseManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, baseGameId);
|
||||
var baseManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, baseGameId);
|
||||
if (baseManifest == null)
|
||||
{
|
||||
logger?.LogInformation("Unable to read or find manifest for addon game with ID {GameId}. Skip uninstallation!", baseGameId);
|
||||
|
|
@ -748,19 +750,19 @@ namespace LANCommander.SDK.Services
|
|||
gameFileList.InstallDirectory = installDirectory;
|
||||
|
||||
addonIds ??= [];
|
||||
foreach (var dependentGame in baseManifest.DependentGames)
|
||||
foreach (var addon in baseManifest.Addons)
|
||||
{
|
||||
if (!addonIds.Contains(dependentGame))
|
||||
if (!addonIds.Contains(addon.Id))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
var dependentResult = await UninstallAddonAsync(installDirectory, dependentGame);
|
||||
gameFileList.MergeBaseAsDependentGame(dependentGame, dependentResult.FileList);
|
||||
var dependentResult = await UninstallAddonAsync(installDirectory, addon.Id);
|
||||
gameFileList.MergeBaseAsDependentGame(addon.Id, dependentResult.FileList);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger?.LogWarning(ex, $"Could not uninstall dependent game {dependentGame} of base game {baseGameId}. Assuming it's already uninstalled or never installed...");
|
||||
logger?.LogWarning(ex, $"Could not uninstall dependent game {addon} of base game {baseGameId}. Assuming it's already uninstalled or never installed...");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -772,7 +774,7 @@ namespace LANCommander.SDK.Services
|
|||
var installResult = new InstallResult(installDirectory, addonGameId);
|
||||
var gameFileList = installResult.FileList;
|
||||
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, addonGameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, addonGameId);
|
||||
|
||||
if (manifest != null)
|
||||
{
|
||||
|
|
@ -914,12 +916,16 @@ namespace LANCommander.SDK.Services
|
|||
await WriteScriptsAsync(installDirectory, game);
|
||||
}
|
||||
|
||||
private async Task<GameManifest> WriteManifestAsync(string installDirectory, Game game)
|
||||
private async Task<Models.Manifest.Game> WriteManifestAsync(string installDirectory, Game game)
|
||||
{
|
||||
logger?.LogTrace($"Retrieving game manifest for game {game.Title} with id {game.Id}");
|
||||
GameManifest manifest = await GetManifestAsync(game.Id);
|
||||
|
||||
var manifest = await GetManifestAsync(game.Id);
|
||||
|
||||
logger?.LogTrace($"Saving Manifest for game {game.Id} into {installDirectory}");
|
||||
|
||||
await ManifestHelper.WriteAsync(manifest, installDirectory);
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
|
|
@ -1177,30 +1183,30 @@ namespace LANCommander.SDK.Services
|
|||
_reader?.Cancel();
|
||||
}
|
||||
|
||||
public async Task<ICollection<GameManifest>> ReadManifestsAsync(string installDirectory, Guid gameId)
|
||||
public async Task<ICollection<SDK.Models.Manifest.Game>> ReadManifestsAsync(string installDirectory, Guid gameId)
|
||||
{
|
||||
var manifests = new List<GameManifest>();
|
||||
var mainManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifests = new List<SDK.Models.Manifest.Game>();
|
||||
var mainManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
|
||||
if (mainManifest == null)
|
||||
return manifests;
|
||||
|
||||
manifests.Add(mainManifest);
|
||||
|
||||
if (mainManifest.DependentGames != null)
|
||||
if (mainManifest.Addons != null)
|
||||
{
|
||||
foreach (var dependentGameId in mainManifest.DependentGames)
|
||||
foreach (var addon in mainManifest.Addons)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dependentGameManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, dependentGameId);
|
||||
var dependentGameManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, addon.Id);
|
||||
|
||||
if (dependentGameManifest.Type == GameType.Expansion || dependentGameManifest.Type == GameType.Mod)
|
||||
manifests.Add(dependentGameManifest);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger?.LogError(ex, "Could not load manifest from dependent game {DependentGameId}", dependentGameId);
|
||||
logger?.LogError(ex, "Could not load manifest from dependent game {AddonId}", addon.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1220,7 +1226,7 @@ namespace LANCommander.SDK.Services
|
|||
/// <exception cref="Exception">
|
||||
/// Thrown if the request to retrieve archive entries encounters an error.
|
||||
/// </exception>
|
||||
protected async Task<IEnumerable<ArchiveEntry>> GetGameInstallationArchiveEntries(Guid gameId, GameManifest manifest)
|
||||
protected async Task<IEnumerable<ArchiveEntry>> GetGameInstallationArchiveEntries(Guid gameId, Models.Manifest.Game manifest)
|
||||
{
|
||||
var entries = await apiRequestFactory
|
||||
.Create()
|
||||
|
|
@ -1266,10 +1272,10 @@ namespace LANCommander.SDK.Services
|
|||
{
|
||||
var depEntries = await GetGameInstallationArchiveEntries(gameId, depManifest);
|
||||
|
||||
if (!gameArchives.DependentGames.TryGetValue(depManifest.Id, out var depArchiveInfo))
|
||||
if (!gameArchives.Addons.TryGetValue(depManifest.Id, out var depArchiveInfo))
|
||||
{
|
||||
depArchiveInfo = new();
|
||||
gameArchives.DependentGames.Add(depManifest.Id, depArchiveInfo);
|
||||
gameArchives.Addons.Add(depManifest.Id, depArchiveInfo);
|
||||
}
|
||||
|
||||
depArchiveInfo.Manifest = depManifest;
|
||||
|
|
@ -1282,7 +1288,7 @@ namespace LANCommander.SDK.Services
|
|||
return gameArchives;
|
||||
}
|
||||
|
||||
public async Task RunAsync(string installDirectory, Guid gameId, Models.Action action, DateTime? lastRun, string args = "")
|
||||
public async Task RunAsync(string installDirectory, Guid gameId, Models.Manifest.Action action, DateTime? lastRun, string args = "")
|
||||
{
|
||||
var screen = DisplayHelper.GetScreen();
|
||||
|
||||
|
|
@ -1420,7 +1426,7 @@ namespace LANCommander.SDK.Services
|
|||
}
|
||||
}
|
||||
|
||||
private async Task UploadSavesAsync(ICollection<GameManifest> manifests, string installDirectory)
|
||||
private async Task UploadSavesAsync(ICollection<SDK.Models.Manifest.Game> manifests, string installDirectory)
|
||||
{
|
||||
if (connectionClient.IsConnected())
|
||||
{
|
||||
|
|
@ -1526,7 +1532,7 @@ namespace LANCommander.SDK.Services
|
|||
var manifest = archives?.BaseGame?.Entries;
|
||||
var entries = archives?.BaseGame?.Entries?.ToList() ?? [];
|
||||
|
||||
foreach ((var dependentGameId, var dependentGameInfo) in archives?.DependentGames ?? [])
|
||||
foreach ((var dependentGameId, var dependentGameInfo) in archives?.Addons ?? [])
|
||||
{
|
||||
foreach (var depArchive in dependentGameInfo.Entries ?? [])
|
||||
{
|
||||
|
|
@ -1545,14 +1551,14 @@ namespace LANCommander.SDK.Services
|
|||
}
|
||||
|
||||
// lookup for dependent games
|
||||
var lookupEntry = archives?.DependentGames?
|
||||
var lookupEntry = archives?.Addons?
|
||||
.SelectMany(dep => dep.Value?.Entries?.Select(entry => new { GameId = (Guid?)dep.Key, ArchiveEntry = entry }) ?? [])
|
||||
.ToLookup(tentry => tentry.ArchiveEntry, tentry => tentry.GameId) ?? Enumerable.Empty<Guid?>().ToLookup(x => default(ArchiveEntry));
|
||||
|
||||
var conflictedEntries = new List<ArchiveValidationConflict>();
|
||||
|
||||
var savePathEntries = archives?.BaseGame?.SavePaths.ToList() ?? [];
|
||||
var depSavePathEntries = archives?.DependentGames?.SelectMany(dep => dep.Value?.SavePaths ?? []).ToList() ?? [];
|
||||
var depSavePathEntries = archives?.Addons?.SelectMany(dep => dep.Value?.SavePaths ?? []).ToList() ?? [];
|
||||
savePathEntries.AddRange(depSavePathEntries);
|
||||
|
||||
foreach (var entry in entries)
|
||||
|
|
@ -1637,7 +1643,7 @@ namespace LANCommander.SDK.Services
|
|||
/// <param name="entries">A collection of file paths to download.</param>
|
||||
public async Task DownloadFilesAsync(string installDirectory, Guid gameId, ICollection<string> entries)
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace LANCommander.SDK.Services
|
|||
|
||||
public async Task DownloadAsync(string installDirectory, Guid gameId, Guid? saveId = null)
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
|
||||
string tempFile;
|
||||
string tempLocation = string.Empty;
|
||||
|
|
@ -144,7 +144,7 @@ namespace LANCommander.SDK.Services
|
|||
if (!success)
|
||||
throw new ExtractionException("Could not extract the save archive. Is the file locked?");
|
||||
|
||||
manifest = await ManifestHelper.ReadAsync<GameManifest>(tempLocation);
|
||||
manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(tempLocation);
|
||||
|
||||
#region Move files
|
||||
var tempLocationFilePath = "Files";
|
||||
|
|
@ -240,7 +240,7 @@ namespace LANCommander.SDK.Services
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<Stream> PackAsync(string installDirectory, GameManifest manifest)
|
||||
public async Task<Stream> PackAsync(string installDirectory, SDK.Models.Manifest.Game manifest)
|
||||
{
|
||||
using (var savePacker = new SavePacker(installDirectory))
|
||||
{
|
||||
|
|
@ -253,7 +253,7 @@ namespace LANCommander.SDK.Services
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<GameSave> UploadAsync(Stream stream, GameManifest manifest)
|
||||
public async Task<GameSave> UploadAsync(Stream stream, SDK.Models.Manifest.Game manifest)
|
||||
{
|
||||
return await apiRequestFactory
|
||||
.Create()
|
||||
|
|
@ -267,7 +267,7 @@ namespace LANCommander.SDK.Services
|
|||
{
|
||||
using (var savePacker = new SavePacker(installDirectory))
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
|
||||
if (manifest?.SavePaths?.Any() ?? false)
|
||||
savePacker.AddPaths(manifest.SavePaths);
|
||||
|
|
@ -293,7 +293,7 @@ namespace LANCommander.SDK.Services
|
|||
.DeleteAsync<bool>();
|
||||
}
|
||||
|
||||
public IEnumerable<SavePathEntry> GetFileSavePathEntries(SavePath savePath, string installDirectory)
|
||||
public IEnumerable<SavePathEntry> GetFileSavePathEntries(SDK.Models.Manifest.SavePath savePath, string installDirectory)
|
||||
{
|
||||
IEnumerable<string> localPaths;
|
||||
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ namespace LANCommander.SDK.Services
|
|||
{
|
||||
bool result = default;
|
||||
|
||||
var gameManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var redistributableManifest = await ManifestHelper.ReadAsync<Redistributable>(installDirectory, redistributableId);
|
||||
var gameManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var redistributableManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Redistributable>(installDirectory, redistributableId);
|
||||
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, redistributableId, Enums.ScriptType.DetectInstall);
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ namespace LANCommander.SDK.Services
|
|||
{
|
||||
int result = default;
|
||||
|
||||
var gameManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var gameManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var redistributableManifest = await ManifestHelper.ReadAsync<Redistributable>(installDirectory, redistributableId);
|
||||
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, redistributableId, Enums.ScriptType.Install);
|
||||
|
|
@ -259,7 +259,7 @@ namespace LANCommander.SDK.Services
|
|||
|
||||
try
|
||||
{
|
||||
var gameManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var gameManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var redistributableManifest = await ManifestHelper.ReadAsync<Redistributable>(installDirectory, redistributableId);
|
||||
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, redistributableId, Enums.ScriptType.BeforeStart);
|
||||
|
|
@ -339,7 +339,7 @@ namespace LANCommander.SDK.Services
|
|||
|
||||
try
|
||||
{
|
||||
var gameManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var gameManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var redistributableManifest = await ManifestHelper.ReadAsync<Redistributable>(installDirectory, redistributableId);
|
||||
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, redistributableId, Enums.ScriptType.AfterStop);
|
||||
|
|
@ -419,7 +419,7 @@ namespace LANCommander.SDK.Services
|
|||
|
||||
try
|
||||
{
|
||||
var gameManifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var gameManifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var redistributableManifest = await ManifestHelper.ReadAsync<Redistributable>(installDirectory, redistributableId);
|
||||
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, redistributableId, Enums.ScriptType.NameChange);
|
||||
|
|
@ -512,7 +512,7 @@ namespace LANCommander.SDK.Services
|
|||
|
||||
try
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, gameId, Enums.ScriptType.Install);
|
||||
|
||||
using (var op = logger.BeginOperation("Executing install script"))
|
||||
|
|
@ -579,7 +579,7 @@ namespace LANCommander.SDK.Services
|
|||
|
||||
try
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, gameId, Enums.ScriptType.Uninstall);
|
||||
|
||||
using (var op = logger.BeginOperation("Executing uninstall script"))
|
||||
|
|
@ -646,7 +646,7 @@ namespace LANCommander.SDK.Services
|
|||
|
||||
try
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, gameId, Enums.ScriptType.BeforeStart);
|
||||
|
||||
using (var op = logger.BeginOperation("Executing before start script"))
|
||||
|
|
@ -716,7 +716,7 @@ namespace LANCommander.SDK.Services
|
|||
|
||||
try
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, gameId, Enums.ScriptType.AfterStop);
|
||||
|
||||
using (var op = logger.BeginOperation("Executing after stop script"))
|
||||
|
|
@ -786,7 +786,7 @@ namespace LANCommander.SDK.Services
|
|||
try
|
||||
{
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, gameId, Enums.ScriptType.NameChange);
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
|
||||
using (var op = logger.BeginOperation("Executing name change script"))
|
||||
{
|
||||
|
|
@ -869,7 +869,7 @@ namespace LANCommander.SDK.Services
|
|||
try
|
||||
{
|
||||
var path = ScriptHelper.GetScriptFilePath(installDirectory, gameId, Enums.ScriptType.KeyChange);
|
||||
var manifest = await ManifestHelper.ReadAsync<GameManifest>(installDirectory, gameId);
|
||||
var manifest = await ManifestHelper.ReadAsync<SDK.Models.Manifest.Game>(installDirectory, gameId);
|
||||
|
||||
using (var op = logger.BeginOperation("Executing key change script"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class SavePacker : IDisposable
|
|||
_archive = ZipArchive.Create();
|
||||
}
|
||||
|
||||
public SavePacker AddPath(SavePath path)
|
||||
public SavePacker AddPath(SDK.Models.Manifest.SavePath path)
|
||||
{
|
||||
switch (path.Type)
|
||||
{
|
||||
|
|
@ -52,7 +52,7 @@ public class SavePacker : IDisposable
|
|||
return this;
|
||||
}
|
||||
|
||||
public SavePacker AddPaths(IEnumerable<SavePath> paths)
|
||||
public SavePacker AddPaths(IEnumerable<SDK.Models.Manifest.SavePath> paths)
|
||||
{
|
||||
foreach (var path in paths)
|
||||
{
|
||||
|
|
@ -62,7 +62,7 @@ public class SavePacker : IDisposable
|
|||
return this;
|
||||
}
|
||||
|
||||
public SavePacker AddRegistryPath(SavePath registryPath)
|
||||
public SavePacker AddRegistryPath(SDK.Models.Manifest.SavePath registryPath)
|
||||
{
|
||||
if (registryPath.Type != SavePathType.Registry)
|
||||
return this;
|
||||
|
|
@ -80,7 +80,7 @@ public class SavePacker : IDisposable
|
|||
return this;
|
||||
}
|
||||
|
||||
public async Task AddManifestAsync(GameManifest manifest)
|
||||
public async Task AddManifestAsync(Models.Manifest.Game manifest)
|
||||
{
|
||||
_archive.AddEntry(ManifestHelper.ManifestFilename, new MemoryStream(Encoding.UTF8.GetBytes(ManifestHelper.Serialize(manifest))));
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ public class SavePacker : IDisposable
|
|||
return _stream;
|
||||
}
|
||||
|
||||
private void AddEntriesFromPath(SavePath savePath)
|
||||
private void AddEntriesFromPath(SDK.Models.Manifest.SavePath savePath)
|
||||
{
|
||||
if (savePath.IsRegex)
|
||||
AddEntriesFromFilePathPattern(savePath.Id, savePath.Path, savePath.WorkingDirectory);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@ public class ImportContextFactory(IServiceProvider serviceProvider)
|
|||
{
|
||||
var scope = serviceProvider.CreateScope();
|
||||
|
||||
return scope.ServiceProvider.GetService<ImportContext>();
|
||||
return scope.ServiceProvider.GetRequiredService<ImportContext>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
using LANCommander.Server.Data;
|
||||
using LANCommander.Server.Data.Models;
|
||||
using LANCommander.Helpers;
|
||||
using LANCommander.Server.Models;
|
||||
using LANCommander.SDK;
|
||||
using System.IO.Compression;
|
||||
using System.Linq.Expressions;
|
||||
using AutoMapper;
|
||||
|
|
@ -14,7 +12,6 @@ using LANCommander.Server.Services.Models;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SharpCompress.Common;
|
||||
using PascalCaseNamingConvention = YamlDotNet.Serialization.NamingConventions.PascalCaseNamingConvention;
|
||||
|
||||
namespace LANCommander.Server.Services
|
||||
|
|
@ -118,7 +115,7 @@ namespace LANCommander.Server.Services
|
|||
await base.DeleteAsync(archive);
|
||||
}
|
||||
|
||||
public async Task<GameManifest> ReadManifestAsync(string objectKey)
|
||||
public async Task<SDK.Models.Manifest.Game> ReadManifestAsync(string objectKey)
|
||||
{
|
||||
var upload = await GetArchiveFileLocationAsync(objectKey);
|
||||
|
||||
|
|
@ -145,7 +142,7 @@ namespace LANCommander.Server.Services
|
|||
.WithNamingConvention(new PascalCaseNamingConvention())
|
||||
.Build();
|
||||
|
||||
var manifest = deserializer.Deserialize<GameManifest>(manifestContents);
|
||||
var manifest = deserializer.Deserialize<SDK.Models.Manifest.Game>(manifestContents);
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
|
@ -173,7 +170,7 @@ namespace LANCommander.Server.Services
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<bool> ExistsAsync(Guid archiveId)
|
||||
public override async Task<bool> ExistsAsync(Guid archiveId)
|
||||
{
|
||||
var archive = await Include(a => a.StorageLocation).GetAsync(archiveId);
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ namespace LANCommander.Server.Services
|
|||
return await GetAsync(g => g.AddonTypes.Contains(g.Type));
|
||||
}
|
||||
|
||||
public async Task<GameManifest> GetManifestAsync(Guid id)
|
||||
public async Task<SDK.Models.Manifest.Game> GetManifestAsync(Guid id)
|
||||
{
|
||||
var game = await Query(q =>
|
||||
{
|
||||
|
|
@ -148,138 +148,12 @@ namespace LANCommander.Server.Services
|
|||
return GetManifest(game);
|
||||
}
|
||||
|
||||
public GameManifest GetManifest(Game game)
|
||||
public SDK.Models.Manifest.Game GetManifest(Game game)
|
||||
{
|
||||
if (game == null)
|
||||
return null;
|
||||
|
||||
var manifest = new GameManifest()
|
||||
{
|
||||
Id = game.Id,
|
||||
Title = game.Title,
|
||||
SortTitle = game.SortTitle,
|
||||
Description = game.Description,
|
||||
Notes = game.Notes,
|
||||
ReleasedOn = game.ReleasedOn.GetValueOrDefault(),
|
||||
Singleplayer = game.Singleplayer,
|
||||
Type = (SDK.Enums.GameType)(int)game.Type,
|
||||
};
|
||||
|
||||
if (game.Engine != null)
|
||||
manifest.Engine = game.Engine.Name;
|
||||
|
||||
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.Collections != null && game.Collections.Count > 0)
|
||||
manifest.Collections = game.Collections.Select(c => c.Name).ToArray();
|
||||
|
||||
if (game.Archives != null && game.Archives.Count > 0)
|
||||
manifest.Version = game.Archives.OrderByDescending(a => a.CreatedOn).First().Version;
|
||||
|
||||
if (game.Media != null && game.Media.Count > 0)
|
||||
manifest.Media = mapper.Map<IEnumerable<SDK.Models.Media>>(game.Media);
|
||||
|
||||
if (game.Actions != null && game.Actions.Count > 0)
|
||||
{
|
||||
manifest.Actions = game.Actions.Select(a => new SDK.Models.Action()
|
||||
{
|
||||
Name = a.Name,
|
||||
Arguments = a.Arguments,
|
||||
Path = a.Path,
|
||||
WorkingDirectory = a.WorkingDirectory,
|
||||
IsPrimaryAction = a.PrimaryAction,
|
||||
SortOrder = a.SortOrder,
|
||||
}).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,
|
||||
Description = local.Description,
|
||||
NetworkProtocol = local.NetworkProtocol,
|
||||
};
|
||||
|
||||
if (lan != null)
|
||||
manifest.LanMultiplayer = new MultiplayerInfo()
|
||||
{
|
||||
MinPlayers = lan.MinPlayers,
|
||||
MaxPlayers = lan.MaxPlayers,
|
||||
Description = lan.Description,
|
||||
NetworkProtocol = lan.NetworkProtocol,
|
||||
};
|
||||
|
||||
if (online != null)
|
||||
manifest.OnlineMultiplayer = new MultiplayerInfo()
|
||||
{
|
||||
MinPlayers = online.MinPlayers,
|
||||
MaxPlayers = online.MaxPlayers,
|
||||
Description = online.Description,
|
||||
NetworkProtocol = online.NetworkProtocol,
|
||||
};
|
||||
}
|
||||
|
||||
if (game.SavePaths != null && game.SavePaths.Count > 0)
|
||||
{
|
||||
manifest.SavePaths = game.SavePaths.Select(p => new SDK.Models.SavePath()
|
||||
{
|
||||
Id = p.Id,
|
||||
Path = p.Path,
|
||||
IsRegex = p.IsRegex,
|
||||
WorkingDirectory = p.WorkingDirectory,
|
||||
Type = p.Type
|
||||
});
|
||||
}
|
||||
|
||||
if (game.Scripts != null && game.Scripts.Count > 0)
|
||||
{
|
||||
manifest.Scripts = game.Scripts.Select(p => new SDK.Models.Script()
|
||||
{
|
||||
Id = p.Id,
|
||||
Type = p.Type,
|
||||
Name = p.Name,
|
||||
Description = p.Description,
|
||||
RequiresAdmin = p.RequiresAdmin
|
||||
});
|
||||
}
|
||||
|
||||
if (game.Redistributables != null && game.Redistributables.Count > 0)
|
||||
{
|
||||
manifest.Redistributables = game.Redistributables.Select(p => new SDK.Models.Redistributable()
|
||||
{
|
||||
Id = p.Id,
|
||||
Name = p.Name,
|
||||
Description = p.Description,
|
||||
Notes = p.Notes
|
||||
});
|
||||
}
|
||||
|
||||
if (game.DependentGames != null && game.DependentGames.Count > 0)
|
||||
{
|
||||
manifest.DependentGames = game.DependentGames.Select(g => g.Id).ToArray();
|
||||
}
|
||||
|
||||
if (game.CustomFields != null && game.CustomFields.Count > 0)
|
||||
{
|
||||
manifest.CustomFields = game.CustomFields.Select(cf => new SDK.Models.GameCustomField(cf.Name, cf.Value)).ToArray();
|
||||
}
|
||||
var manifest = mapper.Map<SDK.Models.Manifest.Game>(game);
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ public static class GameEndpoints
|
|||
[FromServices] IMapper mapper,
|
||||
Guid id)
|
||||
{
|
||||
var game = await cache.GetOrSetAsync<SDK.Models.Game>($"Games/{id}", async _ =>
|
||||
var game = await cache.GetOrSetAsync<SDK.Models.Manifest.Game>($"Games/{id}", async _ =>
|
||||
{
|
||||
var result = await gameService
|
||||
.Include(g => g.Actions)
|
||||
|
|
@ -112,7 +112,7 @@ public static class GameEndpoints
|
|||
.AsSplitQuery()
|
||||
.GetAsync(id);
|
||||
|
||||
return mapper.Map<SDK.Models.Game>(result);
|
||||
return mapper.Map<SDK.Models.Manifest.Game>(result);
|
||||
}, TimeSpan.MaxValue, tags: ["Games", $"Games/{id}"]);
|
||||
|
||||
if (game != null)
|
||||
|
|
@ -127,7 +127,7 @@ public static class GameEndpoints
|
|||
Guid id)
|
||||
{
|
||||
var manifest = await cache
|
||||
.GetOrSetAsync<SDK.GameManifest>(
|
||||
.GetOrSetAsync<SDK.Models.Manifest.Game>(
|
||||
$"Game/{id}/Manifest",
|
||||
async _ => await gameService.GetManifestAsync(id),
|
||||
TimeSpan.MaxValue,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue