sa/Stars Assistant/Services/Game.cs
2024-09-26 22:18:50 +02:00

184 lines
5.9 KiB
C#

using System.Reflection.PortableExecutable;
using Splat;
using StarsAssistant.Model;
namespace StarsAssistant.Services;
public class Game
{
/// <summary>
/// Default constructor, initialize required fields manually, targeted
/// for Initial DB creation.
/// </summary>
public Game() {}
/// <summary>
/// Init game state from database, targeted for CLI arg.
/// </summary>
/// <param name="dbGame">Record loaded from DB</param>
public Game(Model.Game dbGame)
{
GamePath = dbGame.GamePath;
BaseName = dbGame.BaseName;
}
/// <summary>
/// Helper to construct the game from a command line.
/// </summary>
/// <param name="args">The command line to parse.</param>
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;
}
}
/// <summary>
/// The base path in which all game files reside.
/// </summary>
public string GamePath { get; set; } = String.Empty;
/// <summary>
/// The base name without extensions of your game, inside the GamePath folder.
/// All dependant files are resolved using this name.
/// </summary>
public string BaseName { get; set; } = String.Empty;
/// <summary>
/// Combine into the DatabaseName
/// </summary>
public string DatabaseFileName => Path.Combine(GamePath, $"{BaseName}.sqlite");
/// <summary>
/// Search for Planet files using this pattern, will give you all pxx files.
/// </summary>
public string PlanetFileSearchPattern => $"{BaseName}.p*";
/// <summary>
/// Internal helper to lazily load the current player from the DB.
/// </summary>
private readonly static Lazy<Race>LazyPlayer = new ( () => {
using var db = Locator.Current.GetService<StarsDatabase>()!;
Race result = db.Race
.Where(r => r.PlayerRace == true)
.First();
return result;
});
/// <summary>
/// Get the Race object for the current player, lazy initialized.
/// </summary>
public static Race Player => LazyPlayer.Value;
/// <summary>
/// Get the name of a planet file for a given race.
/// </summary>
/// <param name="r">The race to load.</param>
/// <returns>Fully qualified file path.</returns>
public string PlanetFileForRace (Race r) => Path.Combine(GamePath, $"{BaseName}.p{r.PlayerFileId}");
/// <summary>
/// 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.
/// </summary>
/// <param name="db">Optional DB instance if services are yet unavailable.</param>
public void SaveToDatabase(StarsDatabase? db = null)
{
db ??= Locator.Current.GetService<StarsDatabase>()!;
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();
}
/// <summary>
/// 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.
/// </summary>
public void RegisterServicesForGame()
{
Locator.CurrentMutable.RegisterConstant(this, typeof(Services.Game));
GameEngine.Game = this;
Locator.CurrentMutable.RegisterConstant(new CSVDataLoader(), typeof(CSVDataLoader));
Locator.CurrentMutable.Register(() => new StarsDatabase(DatabaseFileName), typeof(StarsDatabase));
PlanetManager PlanetManager = new();
Locator.CurrentMutable.RegisterConstant(PlanetManager, typeof(Services.PlanetManager));
// TESTING HELPER
if (__doCreateTestData)
__createTestData();
PlanetManager.InitFromDatabase();
}
/// <summary>
/// Starts all required background servies, so that we are in normal UI
/// operation mode. This is called after the UI is up and running.
/// </summary>
public void StartBackgroundServices()
{
CSVDataLoader csvloader = Locator.Current.GetService<Services.CSVDataLoader>()!;
csvloader.StartCSVWatcher();
}
private bool __doCreateTestData = false;
/// <summary>
/// TESTING HELPER
/// </summary>
private void __createTestData ()
{
using var db = Locator.Current.GetService<StarsDatabase>()!;
// 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 = 9,
FactoryResCost = 9,
FactoryResPer10 = 15,
MineResCost = 3,
MineMineralsPer10 = 10,
MineNumberPer10k = 10
};
db.Add(r);
db.SaveChanges();
var loader = new CSV.PlanetLoader();
loader.ImportForRace(Services.Game.Player);
}
}