using System.Reflection.PortableExecutable; using Splat; using StarsAssistant.Model; namespace StarsAssistant.Services; public class Game { /// /// Default constructor, initialize required fields manually, targeted /// for Initial DB creation. /// public Game() {} /// /// Init game state from database, targeted for CLI arg. /// /// Record loaded from DB public Game(Model.Game dbGame) { GamePath = dbGame.GamePath; BaseName = dbGame.BaseName; } /// /// Helper to construct the game from a command line. /// /// The command line to parse. public Game(string[]? args) { GamePath = "/home/torben/Nextcloud/Documents/Stars!/Games/goingth/"; BaseName = "GOINGTH"; string dbPath = DatabaseFileName; using StarsDatabase starsDB = new(dbPath); if (Path.Exists(dbPath)) { Model.Game dbGame = starsDB.Game.First(); } else { starsDB.Database.EnsureCreated(); SaveToDatabase(starsDB); __doCreateTestData = true; } } /// /// The base path in which all game files reside. /// public string GamePath { get; set; } = String.Empty; /// /// The base name without extensions of your game, inside the GamePath folder. /// All dependant files are resolved using this name. /// public string BaseName { get; set; } = String.Empty; /// /// Combine into the DatabaseName /// public string DatabaseFileName => Path.Combine(GamePath, $"{BaseName}.sqlite"); /// /// Search for Planet files using this pattern, will give you all pxx files. /// public string PlanetFileSearchPattern => $"{BaseName}.p*"; /// /// Internal helper to lazily load the current player from the DB. /// private readonly static LazyLazyPlayer = new ( () => { using var db = Locator.Current.GetService()!; Race result = db.Race .Where(r => r.PlayerRace == true) .First(); return result; }); /// /// Get the Race object for the current player, lazy initialized. /// public static Race Player => LazyPlayer.Value; /// /// Get the name of a planet file for a given race. /// /// The race to load. /// Fully qualified file path. public string PlanetFileForRace (Race r) => Path.Combine(GamePath, $"{BaseName}.p{r.PlayerFileId}"); /// /// Save this record in the database. Uses the service locator to access the /// database unless you specify an instance. This is needed during initial /// game creation, where the services are not yet established. /// /// Optional DB instance if services are yet unavailable. public void SaveToDatabase(StarsDatabase? db = null) { db ??= Locator.Current.GetService()!; Model.Game? dbGame = db.Game.FirstOrDefault(); if (dbGame == null) { dbGame = new Model.Game(); db.Add(dbGame); db.SaveChanges(); } dbGame.GamePath = GamePath; dbGame.BaseName = BaseName; db.Update(dbGame); db.SaveChanges(); } /// /// Registers all services depending on this Game, in the order required. /// This is called once the framework is initialized but before the main /// window is active and has its models. /// public void RegisterServicesForGame() { Locator.CurrentMutable.RegisterConstant(this, typeof(Services.Game)); Locator.CurrentMutable.RegisterConstant(new CSVDataLoader(), typeof(CSVDataLoader)); Locator.CurrentMutable.Register(() => new StarsDatabase(DatabaseFileName), typeof(StarsDatabase)); // TESTING HELPER if (__doCreateTestData) __createTestData(); } /// /// Starts all required background servies, so that we are in normal UI /// operation mode. This is called after the UI is up and running. /// public void StartBackgroundServices() { CSVDataLoader csvloader = Locator.Current.GetService()!; csvloader.StartCSVWatcher(); } private bool __doCreateTestData = false; /// /// TESTING HELPER /// private void __createTestData () { using var db = Locator.Current.GetService()!; // Note: This sample requires the database to be created before running. // Console.WriteLine($"Database path: {db.DbPath}."); Race r = new() { Name = "Atlantis", PlayerRace = true, PlayerFileId = 1, ColonistsPerResource = 1000, GrowthRatePercent = 19, PRT = PRT.Other, HasOBRM = true, FactoryCost3 = false, FactoryNumberPer10k = 8, FactoryResCost = 8, FactoryResPer10 = 15, MineResCost = 3, MineMineralsPer10 = 10, MineNumberPer10k = 10 }; db.Add(r); db.SaveChanges(); var loader = new CSV.PlanetLoader(); loader.ImportForRace(Services.Game.Player); } }