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<ArkServerSettings>(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<LootDropOverride>(_settings.LootDropOverrides);
Engrams = new ObservableCollection<EngramOverride>(_settings.EngramOverrides);
Creatures = new ObservableCollection<CreatureMultiplier>(_settings.CreatureMultipliers);
StackSizes = new ObservableCollection<StackSizeOverride>(_settings.StackSizeOverrides);
Harvests = new ObservableCollection<HarvestMultiplier>(_settings.HarvestMultipliers);
SpawnOverrides = new ObservableCollection<SpawnOverride>(_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<ServerTemplate>(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<LootDropOverride> LootDrops { get; }
public ObservableCollection<EngramOverride> Engrams { get; }
public ObservableCollection<CreatureMultiplier> Creatures { get; }
public ObservableCollection<LootItemSet>? CurrentSets =>
SelectedDrop != null ? new ObservableCollection<LootItemSet>(SelectedDrop.ItemSets) : null;
public ObservableCollection<LootItem>? CurrentItems =>
SelectedSet != null ? new ObservableCollection<LootItem>(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<StackSizeOverride> StackSizes { get; }
public ObservableCollection<HarvestMultiplier> Harvests { get; }
public ObservableCollection<SpawnOverride> SpawnOverrides { get; }
public ObservableCollection<PerLevelStatRow> 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<EngramOverride> FilteredEngrams =>
string.IsNullOrWhiteSpace(EngramSearch) ? Engrams
: Engrams.Where(e => e.DisplayName.Contains(EngramSearch, StringComparison.OrdinalIgnoreCase)
|| e.EngramClassName.Contains(EngramSearch, StringComparison.OrdinalIgnoreCase));
public IEnumerable<CreatureMultiplier> 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<string> 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<ServerTemplate> Templates => TemplateService.GetArkTemplates();
// ── Library Data ─────────────────────────────────────────────────────
public IReadOnlyList<ArkEngram> EngramLibrary => EngramLibraryService.GetEngramsForGame(Game);
public IReadOnlyList<ArkLootContainer> 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<PerLevelStatRow> BuildPerLevelRows()
{
var ps = _settings.PerLevelStats;
var rows = new ObservableCollection<PerLevelStatRow>();
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();
}
}