using GsConfigTool.Helpers; using GsConfigTool.Models; using GsConfigTool.Services; using Microsoft.Win32; using System.Collections.ObjectModel; using System.IO; using System.Text.Json; using System.Windows; using System.Windows.Input; namespace GsConfigTool.ViewModels; public class ArkConfigViewModel : BaseViewModel { private readonly DatabaseService _db; private readonly MainViewModel _main; private ServerProject _project; private ArkServerSettings _settings; private string _generatedGameIni = ""; private string _generatedGUS = ""; private int _selectedTab; private string _projectName; private string _projectDescription; private LootDropOverride? _selectedDrop; private LootItemSet? _selectedSet; private EngramOverride? _selectedEngram; private CreatureMultiplier? _selectedCreature; private StackSizeOverride? _selectedStackSize; private HarvestMultiplier? _selectedHarvest; private SpawnOverride? _selectedSpawn; private bool _isDirty; private string _engramSearch = ""; private string _creatureSearch = ""; public ArkConfigViewModel(DatabaseService db, MainViewModel main, GameType game, ServerProject? project = null) { _db = db; _main = main; if (project != null) { _project = project; _settings = JsonSerializer.Deserialize(project.ConfigJson) ?? new ArkServerSettings(); } else { _project = new ServerProject { Game = game, Name = $"Neuer {(game == GameType.ArkSurvivalAscended ? "ASA" : "ASE")} Server" }; _settings = new ArkServerSettings(); } Game = game; _projectName = _project.Name; _projectDescription = _project.Description; LootDrops = new ObservableCollection(_settings.LootDropOverrides); Engrams = new ObservableCollection(_settings.EngramOverrides); Creatures = new ObservableCollection(_settings.CreatureMultipliers); StackSizes = new ObservableCollection(_settings.StackSizeOverrides); Harvests = new ObservableCollection(_settings.HarvestMultipliers); SpawnOverrides = new ObservableCollection(_settings.SpawnOverrides); PerLevelRows = BuildPerLevelRows(); SaveCommand = new RelayCommand(async () => await SaveAsync()); SaveAsFileCommand = new RelayCommand(SaveAsFile); CopyGameIniCommand = new RelayCommand(() => CopyToClipboard(GeneratedGameIni)); CopyGUSCommand = new RelayCommand(() => CopyToClipboard(GeneratedGUS)); GoBackCommand = new RelayCommand(() => _main.NavigateTo("Home")); AddLootDropCommand = new RelayCommand(AddLootDrop); RemoveLootDropCommand = new RelayCommand(RemoveLootDrop, () => SelectedDrop != null); AddLootSetCommand = new RelayCommand(AddLootSet, () => SelectedDrop != null); RemoveLootSetCommand = new RelayCommand(RemoveLootSet, () => SelectedSet != null); AddLootItemCommand = new RelayCommand(AddLootItem, () => SelectedSet != null); AddEngramCommand = new RelayCommand(AddEngram); RemoveEngramCommand = new RelayCommand(RemoveEngram, () => SelectedEngram != null); AddCreatureCommand = new RelayCommand(AddCreature); RemoveCreatureCommand = new RelayCommand(RemoveCreature, () => SelectedCreature != null); AddStackSizeCommand = new RelayCommand(AddStackSize); RemoveStackSizeCommand = new RelayCommand(RemoveStackSize, () => SelectedStackSize != null); AddHarvestCommand = new RelayCommand(AddHarvest); RemoveHarvestCommand = new RelayCommand(RemoveHarvest, () => SelectedHarvest != null); AddSpawnCommand = new RelayCommand(AddSpawn); RemoveSpawnCommand = new RelayCommand(RemoveSpawn, () => SelectedSpawn != null); LoadTemplateCommand = new RelayCommand(LoadTemplate); ImportConfigCommand = new RelayCommand(ImportConfig); ResetPerLevelStatsCommand = new RelayCommand(ResetPerLevelStats); GeneratePreview(); } // ── Identity ────────────────────────────────────────────────────────── public GameType Game { get; } public string GameTitle => Game == GameType.ArkSurvivalAscended ? "ARK: Survival Ascended" : "ARK: Survival Evolved"; public string GameColor => Game == GameType.ArkSurvivalAscended ? "#E04040" : "#FF6B35"; public bool IsDirty { get => _isDirty; set => SetField(ref _isDirty, value); } public string ProjectName { get => _projectName; set { SetField(ref _projectName, value); IsDirty = true; } } public string ProjectDescription { get => _projectDescription; set { SetField(ref _projectDescription, value); IsDirty = true; } } // ── Session ─────────────────────────────────────────────────────────── public string ServerName { get => _settings.ServerName; set { _settings.ServerName = value; OnPropertyChanged(); MarkDirty(); } } public string ServerPassword { get => _settings.ServerPassword; set { _settings.ServerPassword = value; OnPropertyChanged(); MarkDirty(); } } public string AdminPassword { get => _settings.AdminPassword; set { _settings.AdminPassword = value; OnPropertyChanged(); MarkDirty(); } } public int MaxPlayers { get => _settings.MaxPlayers; set { _settings.MaxPlayers = value; OnPropertyChanged(); MarkDirty(); } } public int QueryPort { get => _settings.QueryPort; set { _settings.QueryPort = value; OnPropertyChanged(); MarkDirty(); } } public int GamePort { get => _settings.GamePort; set { _settings.GamePort = value; OnPropertyChanged(); MarkDirty(); } } public string Map { get => _settings.Map; set { _settings.Map = value; OnPropertyChanged(); MarkDirty(); } } public string ActiveMods { get => _settings.ActiveMods; set { _settings.ActiveMods = value; OnPropertyChanged(); MarkDirty(); } } // ── Mode ────────────────────────────────────────────────────────────── public bool PvE { get => _settings.PvE; set { _settings.PvE = value; OnPropertyChanged(); MarkDirty(); } } public bool ServerHardcore { get => _settings.ServerHardcore; set { _settings.ServerHardcore = value; OnPropertyChanged(); MarkDirty(); } } public bool CrosshairEnabled { get => _settings.CrosshairEnabled; set { _settings.CrosshairEnabled = value; OnPropertyChanged(); MarkDirty(); } } public bool MapPlayerLocation { get => _settings.MapPlayerLocation; set { _settings.MapPlayerLocation = value; OnPropertyChanged(); MarkDirty(); } } public bool PreventOfflinePvP { get => _settings.PreventOfflinePvP; set { _settings.PreventOfflinePvP = value; OnPropertyChanged(); MarkDirty(); } } public bool PreventTribeAlliances { get => _settings.PreventTribeAlliances; set { _settings.PreventTribeAlliances = value; OnPropertyChanged(); MarkDirty(); } } public bool AllowThirdPersonPlayer { get => _settings.AllowThirdPersonPlayer; set { _settings.AllowThirdPersonPlayer = value; OnPropertyChanged(); MarkDirty(); } } public float KickIdlePlayersPeriod { get => _settings.KickIdlePlayersPeriod; set { _settings.KickIdlePlayersPeriod = value; OnPropertyChanged(); MarkDirty(); } } // ── Rates ───────────────────────────────────────────────────────────── public float XPMultiplier { get => _settings.XPMultiplier; set { _settings.XPMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float TamingSpeedMultiplier { get => _settings.TamingSpeedMultiplier; set { _settings.TamingSpeedMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float HarvestAmountMultiplier { get => _settings.HarvestAmountMultiplier; set { _settings.HarvestAmountMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float HarvestHealthMultiplier { get => _settings.HarvestHealthMultiplier; set { _settings.HarvestHealthMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float ResourcesRespawnPeriodMultiplier { get => _settings.ResourcesRespawnPeriodMultiplier; set { _settings.ResourcesRespawnPeriodMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float DayCycleSpeedScale { get => _settings.DayCycleSpeedScale; set { _settings.DayCycleSpeedScale = value; OnPropertyChanged(); MarkDirty(); } } public float DayTimeSpeedScale { get => _settings.DayTimeSpeedScale; set { _settings.DayTimeSpeedScale = value; OnPropertyChanged(); MarkDirty(); } } public float NightTimeSpeedScale { get => _settings.NightTimeSpeedScale; set { _settings.NightTimeSpeedScale = value; OnPropertyChanged(); MarkDirty(); } } public float DifficultyOffset { get => _settings.DifficultyOffset; set { _settings.DifficultyOffset = value; OnPropertyChanged(); MarkDirty(); } } public float OverrideOfficialDifficulty { get => _settings.OverrideOfficialDifficulty; set { _settings.OverrideOfficialDifficulty = value; OnPropertyChanged(); MarkDirty(); } } // ── Breeding ────────────────────────────────────────────────────────── public float MatingIntervalMultiplier { get => _settings.MatingIntervalMultiplier; set { _settings.MatingIntervalMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float MatingSpeedMultiplier { get => _settings.MatingSpeedMultiplier; set { _settings.MatingSpeedMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float EggHatchSpeedMultiplier { get => _settings.EggHatchSpeedMultiplier; set { _settings.EggHatchSpeedMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float BabyMatureSpeedMultiplier { get => _settings.BabyMatureSpeedMultiplier; set { _settings.BabyMatureSpeedMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float BabyFoodConsumptionSpeedMultiplier { get => _settings.BabyFoodConsumptionSpeedMultiplier; set { _settings.BabyFoodConsumptionSpeedMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float BabyCuddleIntervalMultiplier { get => _settings.BabyCuddleIntervalMultiplier; set { _settings.BabyCuddleIntervalMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float BabyImprintAmountMultiplier { get => _settings.BabyImprintAmountMultiplier; set { _settings.BabyImprintAmountMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float LayEggIntervalMultiplier { get => _settings.LayEggIntervalMultiplier; set { _settings.LayEggIntervalMultiplier = value; OnPropertyChanged(); MarkDirty(); } } // ── Player ──────────────────────────────────────────────────────────── public float PlayerDamageMultiplier { get => _settings.PlayerDamageMultiplier; set { _settings.PlayerDamageMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PlayerResistanceMultiplier { get => _settings.PlayerResistanceMultiplier; set { _settings.PlayerResistanceMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PlayerWaterDrainMultiplier { get => _settings.PlayerWaterDrainMultiplier; set { _settings.PlayerWaterDrainMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PlayerFoodDrainMultiplier { get => _settings.PlayerFoodDrainMultiplier; set { _settings.PlayerFoodDrainMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PlayerStaminaDrainMultiplier { get => _settings.PlayerStaminaDrainMultiplier; set { _settings.PlayerStaminaDrainMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PlayerHealthRecoveryMultiplier { get => _settings.PlayerHealthRecoveryMultiplier; set { _settings.PlayerHealthRecoveryMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PlayerHarvestingDamageMultiplier { get => _settings.PlayerHarvestingDamageMultiplier; set { _settings.PlayerHarvestingDamageMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PlayerTurretDamageMultiplier { get => _settings.PlayerTurretDamageMultiplier; set { _settings.PlayerTurretDamageMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public int OverrideMaxExperiencePointsPlayer { get => _settings.OverrideMaxExperiencePointsPlayer; set { _settings.OverrideMaxExperiencePointsPlayer = value; OnPropertyChanged(); MarkDirty(); } } // ── Dino ────────────────────────────────────────────────────────────── public float DinoDamageMultiplier { get => _settings.DinoDamageMultiplier; set { _settings.DinoDamageMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float DinoResistanceMultiplier { get => _settings.DinoResistanceMultiplier; set { _settings.DinoResistanceMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float TamedDinoDamageMultiplier { get => _settings.TamedDinoDamageMultiplier; set { _settings.TamedDinoDamageMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float TamedDinoResistanceMultiplier { get => _settings.TamedDinoResistanceMultiplier; set { _settings.TamedDinoResistanceMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float DinoHarvestingDamageMultiplier { get => _settings.DinoHarvestingDamageMultiplier; set { _settings.DinoHarvestingDamageMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float DinoTurretDamageMultiplier { get => _settings.DinoTurretDamageMultiplier; set { _settings.DinoTurretDamageMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public int MaxTamedDinos { get => _settings.MaxTamedDinos; set { _settings.MaxTamedDinos = value; OnPropertyChanged(); MarkDirty(); } } public int MaxPersonalTamedDinos { get => _settings.MaxPersonalTamedDinos; set { _settings.MaxPersonalTamedDinos = value; OnPropertyChanged(); MarkDirty(); } } public int OverrideMaxExperiencePointsDino { get => _settings.OverrideMaxExperiencePointsDino; set { _settings.OverrideMaxExperiencePointsDino = value; OnPropertyChanged(); MarkDirty(); } } // ── Structures ──────────────────────────────────────────────────────── public bool DisableStructureDecayPvE { get => _settings.DisableStructureDecayPvE; set { _settings.DisableStructureDecayPvE = value; OnPropertyChanged(); MarkDirty(); } } public float StructureResistanceMultiplier { get => _settings.StructureResistanceMultiplier; set { _settings.StructureResistanceMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PerPlatformMaxStructuresMultiplier { get => _settings.PerPlatformMaxStructuresMultiplier; set { _settings.PerPlatformMaxStructuresMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public bool AllowFlyerCarryPvE { get => _settings.AllowFlyerCarryPvE; set { _settings.AllowFlyerCarryPvE = value; OnPropertyChanged(); MarkDirty(); } } public int MaxNumberOfPlayersInTribe { get => _settings.MaxNumberOfPlayersInTribe; set { _settings.MaxNumberOfPlayersInTribe = value; OnPropertyChanged(); MarkDirty(); } } // ── Items ───────────────────────────────────────────────────────────── public float GlobalSpoilingTimeMultiplier { get => _settings.GlobalSpoilingTimeMultiplier; set { _settings.GlobalSpoilingTimeMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float GlobalItemDecompositionTimeMultiplier { get => _settings.GlobalItemDecompositionTimeMultiplier; set { _settings.GlobalItemDecompositionTimeMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float GlobalCorpseDecompositionTimeMultiplier { get => _settings.GlobalCorpseDecompositionTimeMultiplier; set { _settings.GlobalCorpseDecompositionTimeMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float CropGrowthSpeedMultiplier { get => _settings.CropGrowthSpeedMultiplier; set { _settings.CropGrowthSpeedMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float FuelConsumptionIntervalMultiplier { get => _settings.FuelConsumptionIntervalMultiplier; set { _settings.FuelConsumptionIntervalMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float CustomRecipeEffectivenessMultiplier { get => _settings.CustomRecipeEffectivenessMultiplier; set { _settings.CustomRecipeEffectivenessMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public float PassiveTameFoodConsumptionMultiplier { get => _settings.PassiveTameFoodConsumptionMultiplier; set { _settings.PassiveTameFoodConsumptionMultiplier = value; OnPropertyChanged(); MarkDirty(); } } public bool UnlockAllEngrams { get => _settings.UnlockAllEngrams; set { _settings.UnlockAllEngrams = value; OnPropertyChanged(); MarkDirty(); } } // ── Collections ─────────────────────────────────────────────────────── public ObservableCollection LootDrops { get; } public ObservableCollection Engrams { get; } public ObservableCollection Creatures { get; } public ObservableCollection? CurrentSets => SelectedDrop != null ? new ObservableCollection(SelectedDrop.ItemSets) : null; public ObservableCollection? CurrentItems => SelectedSet != null ? new ObservableCollection(SelectedSet.Items) : null; public LootDropOverride? SelectedDrop { get => _selectedDrop; set { SetField(ref _selectedDrop, value); OnPropertyChanged(nameof(CurrentSets)); } } public LootItemSet? SelectedSet { get => _selectedSet; set { SetField(ref _selectedSet, value); OnPropertyChanged(nameof(CurrentItems)); } } public EngramOverride? SelectedEngram { get => _selectedEngram; set => SetField(ref _selectedEngram, value); } public CreatureMultiplier? SelectedCreature { get => _selectedCreature; set => SetField(ref _selectedCreature, value); } public StackSizeOverride? SelectedStackSize { get => _selectedStackSize; set => SetField(ref _selectedStackSize, value); } public HarvestMultiplier? SelectedHarvest { get => _selectedHarvest; set => SetField(ref _selectedHarvest, value); } public SpawnOverride? SelectedSpawn { get => _selectedSpawn; set => SetField(ref _selectedSpawn, value); } public ObservableCollection StackSizes { get; } public ObservableCollection Harvests { get; } public ObservableCollection SpawnOverrides { get; } public ObservableCollection PerLevelRows { get; private set; } = new(); public bool UseCustomPerLevelStats { get => _settings.UseCustomPerLevelStats; set { _settings.UseCustomPerLevelStats = value; OnPropertyChanged(); MarkDirty(); } } // ── Cluster ─────────────────────────────────────────────────────────── public string ClusterID { get => _settings.Cluster.ClusterID; set { _settings.Cluster.ClusterID = value; OnPropertyChanged(); MarkDirty(); } } public string ClusterPassword { get => _settings.Cluster.ClusterPassword; set { _settings.Cluster.ClusterPassword = value; OnPropertyChanged(); MarkDirty(); } } public bool PreventDownloadSurvivors { get => _settings.Cluster.PreventDownloadSurvivors; set { _settings.Cluster.PreventDownloadSurvivors = value; OnPropertyChanged(); MarkDirty(); } } public bool PreventDownloadItems { get => _settings.Cluster.PreventDownloadItems; set { _settings.Cluster.PreventDownloadItems = value; OnPropertyChanged(); MarkDirty(); } } public bool PreventDownloadDinos { get => _settings.Cluster.PreventDownloadDinos; set { _settings.Cluster.PreventDownloadDinos = value; OnPropertyChanged(); MarkDirty(); } } public bool PreventUploadSurvivors { get => _settings.Cluster.PreventUploadSurvivors; set { _settings.Cluster.PreventUploadSurvivors = value; OnPropertyChanged(); MarkDirty(); } } public bool PreventUploadItems { get => _settings.Cluster.PreventUploadItems; set { _settings.Cluster.PreventUploadItems = value; OnPropertyChanged(); MarkDirty(); } } public bool PreventUploadDinos { get => _settings.Cluster.PreventUploadDinos; set { _settings.Cluster.PreventUploadDinos = value; OnPropertyChanged(); MarkDirty(); } } public bool NoTributeDownloads { get => _settings.Cluster.NoTributeDownloads; set { _settings.Cluster.NoTributeDownloads = value; OnPropertyChanged(); MarkDirty(); } } public bool bAllowUnlimitedRespecs { get => _settings.Cluster.bAllowUnlimitedRespecs; set { _settings.Cluster.bAllowUnlimitedRespecs = value; OnPropertyChanged(); MarkDirty(); } } public int TributeItemExpirationSeconds { get => _settings.Cluster.TributeItemExpirationSeconds; set { _settings.Cluster.TributeItemExpirationSeconds = value; OnPropertyChanged(); MarkDirty(); } } public int TributeDinoExpirationSeconds { get => _settings.Cluster.TributeDinoExpirationSeconds; set { _settings.Cluster.TributeDinoExpirationSeconds = value; OnPropertyChanged(); MarkDirty(); } } public int MaxTribeLogs { get => _settings.Cluster.MaxTribeLogs; set { _settings.Cluster.MaxTribeLogs = value; OnPropertyChanged(); MarkDirty(); } } // ── RCON ────────────────────────────────────────────────────────────── public bool RCONEnabled { get => _settings.RCON.RCONEnabled; set { _settings.RCON.RCONEnabled = value; OnPropertyChanged(); MarkDirty(); } } public int RCONPort { get => _settings.RCON.RCONPort; set { _settings.RCON.RCONPort = value; OnPropertyChanged(); MarkDirty(); } } public int RCONServerGameLogBuffer { get => _settings.RCON.RCONServerGameLogBuffer; set { _settings.RCON.RCONServerGameLogBuffer = value; OnPropertyChanged(); MarkDirty(); } } // ── Search ──────────────────────────────────────────────────────────── public string EngramSearch { get => _engramSearch; set { SetField(ref _engramSearch, value); OnPropertyChanged(nameof(FilteredEngrams)); } } public string CreatureSearch { get => _creatureSearch; set { SetField(ref _creatureSearch, value); OnPropertyChanged(nameof(FilteredCreatures)); } } public IEnumerable FilteredEngrams => string.IsNullOrWhiteSpace(EngramSearch) ? Engrams : Engrams.Where(e => e.DisplayName.Contains(EngramSearch, StringComparison.OrdinalIgnoreCase) || e.EngramClassName.Contains(EngramSearch, StringComparison.OrdinalIgnoreCase)); public IEnumerable FilteredCreatures => string.IsNullOrWhiteSpace(CreatureSearch) ? Creatures : Creatures.Where(c => c.DisplayName.Contains(CreatureSearch, StringComparison.OrdinalIgnoreCase) || c.DinoClassName.Contains(CreatureSearch, StringComparison.OrdinalIgnoreCase)); // ── Map List ────────────────────────────────────────────────────────── public static IReadOnlyList ArkMaps { get; } = new[] { "TheIsland", "ScorchedEarth_P", "Ragnarok", "Aberration_P", "Extinction", "Valguero_P", "Genesis", "CrystalIsles", "Gen2", "LostIsland", "Fjordur", "TheCenter", "TheIsland_WP", "ScorchedEarth_WP", "Aberration_WP", "Extinction_WP", "Genesis2_WP" }; // ── Templates ───────────────────────────────────────────────────────── public IReadOnlyList Templates => TemplateService.GetArkTemplates(); // ── Library Data ───────────────────────────────────────────────────── public IReadOnlyList EngramLibrary => EngramLibraryService.GetEngramsForGame(Game); public IReadOnlyList LootContainerLibrary => EngramLibraryService.GetLootContainersForGame(Game); // ── Preview ─────────────────────────────────────────────────────────── public string GeneratedGameIni { get => _generatedGameIni; private set => SetField(ref _generatedGameIni, value); } public string GeneratedGUS { get => _generatedGUS; private set => SetField(ref _generatedGUS, value); } public int SelectedTab { get => _selectedTab; set { SetField(ref _selectedTab, value); GeneratePreview(); } } // ── Commands ────────────────────────────────────────────────────────── public ICommand SaveCommand { get; } public ICommand SaveAsFileCommand { get; } public ICommand CopyGameIniCommand { get; } public ICommand CopyGUSCommand { get; } public ICommand GoBackCommand { get; } public ICommand AddLootDropCommand { get; } public ICommand RemoveLootDropCommand { get; } public ICommand AddLootSetCommand { get; } public ICommand RemoveLootSetCommand { get; } public ICommand AddLootItemCommand { get; } public ICommand AddEngramCommand { get; } public ICommand RemoveEngramCommand { get; } public ICommand AddCreatureCommand { get; } public ICommand RemoveCreatureCommand { get; } public ICommand AddStackSizeCommand { get; } public ICommand RemoveStackSizeCommand { get; } public ICommand AddHarvestCommand { get; } public ICommand RemoveHarvestCommand { get; } public ICommand AddSpawnCommand { get; } public ICommand RemoveSpawnCommand { get; } public ICommand LoadTemplateCommand { get; } public ICommand ImportConfigCommand { get; } public ICommand ResetPerLevelStatsCommand { get; } private void MarkDirty() { IsDirty = true; GeneratePreview(); } public void GeneratePreview() { SyncCollections(); var (gameIni, gus) = ArkConfigGeneratorService.Generate(_settings); GeneratedGameIni = gameIni; GeneratedGUS = gus; } private void SyncCollections() { _settings.LootDropOverrides = LootDrops.ToList(); _settings.EngramOverrides = Engrams.ToList(); _settings.CreatureMultipliers = Creatures.ToList(); _settings.StackSizeOverrides = StackSizes.ToList(); _settings.HarvestMultipliers = Harvests.ToList(); _settings.SpawnOverrides = SpawnOverrides.ToList(); SyncPerLevelStats(); } private void SyncPerLevelStats() { var ps = _settings.PerLevelStats; foreach (var row in PerLevelRows) { ps.Player[row.Index] = row.Player; ps.PlayerTamed[row.Index] = row.PlayerTamed; ps.DinoWild[row.Index] = row.DinoWild; ps.DinoTamed[row.Index] = row.DinoTamed; ps.DinoTamedAdd[row.Index] = row.DinoTamedAdd; ps.DinoTamedAffinity[row.Index] = row.DinoTamedAffinity; } } private ObservableCollection BuildPerLevelRows() { var ps = _settings.PerLevelStats; var rows = new ObservableCollection(); for (int i = 0; i < 12; i++) rows.Add(new PerLevelStatRow { Index = i, StatName = PerLevelStats.StatNames[i], Player = ps.Player[i], PlayerTamed = ps.PlayerTamed[i], DinoWild = ps.DinoWild[i], DinoTamed = ps.DinoTamed[i], DinoTamedAdd = ps.DinoTamedAdd[i], DinoTamedAffinity = ps.DinoTamedAffinity[i] }); return rows; } private async Task SaveAsync() { SyncCollections(); _project.Name = ProjectName; _project.Description = ProjectDescription; _project.ConfigJson = JsonSerializer.Serialize(_settings); await _db.SaveProjectAsync(_project); IsDirty = false; MessageBox.Show("Projekt gespeichert!", "Gespeichert", MessageBoxButton.OK, MessageBoxImage.Information); } private void SaveAsFile() { SyncCollections(); var dialog = new SaveFileDialog { Title = "Config-Ordner wählen – Game.ini speichern", Filter = "INI Files (*.ini)|*.ini|All Files (*.*)|*.*", FileName = "Game.ini" }; if (dialog.ShowDialog() != true) return; var dir = Path.GetDirectoryName(dialog.FileName)!; var (gameIni, gus) = ArkConfigGeneratorService.Generate(_settings); File.WriteAllText(Path.Combine(dir, "Game.ini"), gameIni); File.WriteAllText(Path.Combine(dir, "GameUserSettings.ini"), gus); MessageBox.Show($"Game.ini & GameUserSettings.ini gespeichert in:\n{dir}", "Export erfolgreich", MessageBoxButton.OK, MessageBoxImage.Information); } private static void CopyToClipboard(string text) { Clipboard.SetText(text); MessageBox.Show("In die Zwischenablage kopiert!", "Kopiert", MessageBoxButton.OK, MessageBoxImage.Information); } // ── Loot Drop Actions ───────────────────────────────────────────────── private void AddLootDrop() { var drop = new LootDropOverride { DropName = "Neuer Drop" }; LootDrops.Add(drop); SelectedDrop = drop; MarkDirty(); } private void RemoveLootDrop() { if (SelectedDrop == null) return; LootDrops.Remove(SelectedDrop); SelectedDrop = null; MarkDirty(); } private void AddLootSet() { if (SelectedDrop == null) return; var set = new LootItemSet { SetName = "Set " + (SelectedDrop.ItemSets.Count + 1) }; SelectedDrop.ItemSets.Add(set); OnPropertyChanged(nameof(CurrentSets)); SelectedSet = set; MarkDirty(); } private void RemoveLootSet() { if (SelectedDrop == null || SelectedSet == null) return; SelectedDrop.ItemSets.Remove(SelectedSet); OnPropertyChanged(nameof(CurrentSets)); SelectedSet = null; MarkDirty(); } private void AddLootItem() { if (SelectedSet == null) return; SelectedSet.Items.Add(new LootItem { DisplayName = "New Item", ItemClassString = "PrimalItemResource_Wood_C" }); OnPropertyChanged(nameof(CurrentItems)); MarkDirty(); } // ── Engram Actions ──────────────────────────────────────────────────── private void AddEngram() { var eng = new EngramOverride { EngramClassName = "EngramEntry_NewEngram_C", DisplayName = "New Engram" }; Engrams.Add(eng); SelectedEngram = eng; MarkDirty(); } private void RemoveEngram() { if (SelectedEngram == null) return; Engrams.Remove(SelectedEngram); SelectedEngram = null; MarkDirty(); } // ── Creature Actions ────────────────────────────────────────────────── private void AddCreature() { var cr = new CreatureMultiplier { DisplayName = "New Creature", DinoClassName = "Dino_BP_C" }; Creatures.Add(cr); SelectedCreature = cr; MarkDirty(); } private void RemoveCreature() { if (SelectedCreature == null) return; Creatures.Remove(SelectedCreature); SelectedCreature = null; MarkDirty(); } // ── StackSize Actions ───────────────────────────────────────────────── private void AddStackSize() { var s = new StackSizeOverride { DisplayName = "Neuer Stack Override", ItemClassString = "PrimalItemResource_Wood_C", MaxItemQuantity = 500 }; StackSizes.Add(s); SelectedStackSize = s; MarkDirty(); } private void RemoveStackSize() { if (SelectedStackSize == null) return; StackSizes.Remove(SelectedStackSize); SelectedStackSize = null; MarkDirty(); } // ── Harvest Actions ─────────────────────────────────────────────────── private void AddHarvest() { var h = new HarvestMultiplier { DisplayName = "Neuer Harvest Override", ClassName = "PrimalItemResource_Wood_C", Multiplier = 2f }; Harvests.Add(h); SelectedHarvest = h; MarkDirty(); } private void RemoveHarvest() { if (SelectedHarvest == null) return; Harvests.Remove(SelectedHarvest); SelectedHarvest = null; MarkDirty(); } // ── Spawn Actions ───────────────────────────────────────────────────── private void AddSpawn() { var s = new SpawnOverride { DisplayName = "Neuer Spawn Override" }; SpawnOverrides.Add(s); SelectedSpawn = s; MarkDirty(); } private void RemoveSpawn() { if (SelectedSpawn == null) return; SpawnOverrides.Remove(SelectedSpawn); SelectedSpawn = null; MarkDirty(); } // ── Template Loading ────────────────────────────────────────────────── private void LoadTemplate(ServerTemplate? template) { if (template?.Settings == null) return; var result = MessageBox.Show( $"Template \"{ template.Name}\" laden?\nAlle aktuellen Einstellungen werden überschrieben!", "Template laden", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result != MessageBoxResult.Yes) return; var oldName = _settings.ServerName; _settings = template.Settings; _settings.ServerName = oldName; RefreshAllProperties(); MarkDirty(); } private void RefreshAllProperties() { LootDrops.Clear(); foreach (var d in _settings.LootDropOverrides) LootDrops.Add(d); Engrams.Clear(); foreach (var e in _settings.EngramOverrides) Engrams.Add(e); Creatures.Clear(); foreach (var c in _settings.CreatureMultipliers) Creatures.Add(c); StackSizes.Clear(); foreach (var s in _settings.StackSizeOverrides) StackSizes.Add(s); Harvests.Clear(); foreach (var h in _settings.HarvestMultipliers) Harvests.Add(h); SpawnOverrides.Clear(); foreach (var s in _settings.SpawnOverrides) SpawnOverrides.Add(s); PerLevelRows.Clear(); foreach (var r in BuildPerLevelRows()) PerLevelRows.Add(r); OnPropertyChanged(string.Empty); } // ── Config Import ───────────────────────────────────────────────────── private void ImportConfig() { var dlg = new OpenFileDialog { Title = "GameUserSettings.ini importieren", Filter = "INI Files (*.ini)|*.ini|All Files (*.*)|*.*", FileName = "GameUserSettings.ini" }; if (dlg.ShowDialog() != true) return; var gusContent = File.ReadAllText(dlg.FileName); string gameIniContent = ""; var dir = Path.GetDirectoryName(dlg.FileName)!; var gameIniPath = Path.Combine(dir, "Game.ini"); if (File.Exists(gameIniPath)) gameIniContent = File.ReadAllText(gameIniPath); else { var g = new OpenFileDialog { Title = "Game.ini importieren (optional)", Filter = "INI Files (*.ini)|*.ini", FileName = "Game.ini" }; if (g.ShowDialog() == true) gameIniContent = File.ReadAllText(g.FileName); } var oldName = _settings.ServerName; _settings = ConfigImportService.ImportArk(gusContent, gameIniContent); if (string.IsNullOrEmpty(_settings.ServerName)) _settings.ServerName = oldName; RefreshAllProperties(); MarkDirty(); MessageBox.Show("Config erfolgreich importiert!", "Import", MessageBoxButton.OK, MessageBoxImage.Information); } // ── Reset PerLevelStats ─────────────────────────────────────────────── private void ResetPerLevelStats() { _settings.PerLevelStats = new PerLevelStats(); PerLevelRows.Clear(); foreach (var r in BuildPerLevelRows()) PerLevelRows.Add(r); MarkDirty(); } }