using GsConfigTool.Models; using System.Globalization; using System.IO; using System.Text.RegularExpressions; namespace GsConfigTool.Services; public static class ConfigImportService { public static ArkServerSettings ImportArk(string gusContent, string gameIniContent) { var s = new ArkServerSettings(); var gus = ParseIni(gusContent); var game = ParseIni(gameIniContent); // Session s.ServerName = gus.Get("SessionSettings", "SessionName", s.ServerName); s.ServerPassword = gus.Get("SessionSettings", "ServerPassword", s.ServerPassword); s.AdminPassword = gus.Get("SessionSettings", "ServerAdminPassword", s.AdminPassword); s.MaxPlayers = gus.GetInt("SessionSettings", "MaxPlayers", s.MaxPlayers); s.QueryPort = gus.GetInt("SessionSettings", "QueryPort", s.QueryPort); // ServerSettings s.PvE = gus.GetBool("ServerSettings", "ServerPVE", s.PvE); s.ServerHardcore = gus.GetBool("ServerSettings", "ServerHardcore", s.ServerHardcore); s.CrosshairEnabled = gus.GetBool("ServerSettings", "ServerCrosshair", s.CrosshairEnabled); s.MapPlayerLocation = gus.GetBool("ServerSettings", "MapPlayerLocation", s.MapPlayerLocation); s.PreventOfflinePvP = gus.GetBool("ServerSettings", "PreventOfflinePvP", s.PreventOfflinePvP); s.PreventTribeAlliances = gus.GetBool("ServerSettings", "PreventTribeAlliances", s.PreventTribeAlliances); s.AllowThirdPersonPlayer = gus.GetBool("ServerSettings", "AllowThirdPersonPlayer", s.AllowThirdPersonPlayer); s.DifficultyOffset = gus.GetFloat("ServerSettings", "DifficultyOffset", s.DifficultyOffset); s.OverrideOfficialDifficulty = gus.GetFloat("ServerSettings", "OverrideOfficialDifficulty", s.OverrideOfficialDifficulty); s.XPMultiplier = gus.GetFloat("ServerSettings", "XPMultiplier", s.XPMultiplier); s.TamingSpeedMultiplier = gus.GetFloat("ServerSettings", "TamingSpeedMultiplier", s.TamingSpeedMultiplier); s.HarvestAmountMultiplier = gus.GetFloat("ServerSettings", "HarvestAmountMultiplier", s.HarvestAmountMultiplier); s.HarvestHealthMultiplier = gus.GetFloat("ServerSettings", "HarvestHealthMultiplier", s.HarvestHealthMultiplier); s.ResourcesRespawnPeriodMultiplier = gus.GetFloat("ServerSettings", "ResourcesRespawnPeriodMultiplier", s.ResourcesRespawnPeriodMultiplier); s.MatingIntervalMultiplier = gus.GetFloat("ServerSettings", "MatingIntervalMultiplier", s.MatingIntervalMultiplier); s.EggHatchSpeedMultiplier = gus.GetFloat("ServerSettings", "EggHatchSpeedMultiplier", s.EggHatchSpeedMultiplier); s.BabyMatureSpeedMultiplier = gus.GetFloat("ServerSettings", "BabyMatureSpeedMultiplier", s.BabyMatureSpeedMultiplier); s.BabyFoodConsumptionSpeedMultiplier = gus.GetFloat("ServerSettings", "BabyFoodConsumptionSpeedMultiplier", s.BabyFoodConsumptionSpeedMultiplier); s.DayCycleSpeedScale = gus.GetFloat("ServerSettings", "DayCycleSpeedScale", s.DayCycleSpeedScale); s.DayTimeSpeedScale = gus.GetFloat("ServerSettings", "DayTimeSpeedScale", s.DayTimeSpeedScale); s.NightTimeSpeedScale = gus.GetFloat("ServerSettings", "NightTimeSpeedScale", s.NightTimeSpeedScale); s.PlayerDamageMultiplier = gus.GetFloat("ServerSettings", "PlayerDamageMultiplier", s.PlayerDamageMultiplier); s.PlayerResistanceMultiplier = gus.GetFloat("ServerSettings", "PlayerResistanceMultiplier", s.PlayerResistanceMultiplier); s.PlayerWaterDrainMultiplier = gus.GetFloat("ServerSettings", "PlayerWaterDrainMultiplier", s.PlayerWaterDrainMultiplier); s.PlayerFoodDrainMultiplier = gus.GetFloat("ServerSettings", "PlayerFoodDrainMultiplier", s.PlayerFoodDrainMultiplier); s.PlayerStaminaDrainMultiplier = gus.GetFloat("ServerSettings", "PlayerStaminaDrainMultiplier", s.PlayerStaminaDrainMultiplier); s.PlayerHealthRecoveryMultiplier = gus.GetFloat("ServerSettings", "PlayerHealthRecoveryMultiplier", s.PlayerHealthRecoveryMultiplier); s.DinoDamageMultiplier = gus.GetFloat("ServerSettings", "DinoDamageMultiplier", s.DinoDamageMultiplier); s.DinoResistanceMultiplier = gus.GetFloat("ServerSettings", "DinoResistanceMultiplier", s.DinoResistanceMultiplier); s.TamedDinoDamageMultiplier = gus.GetFloat("ServerSettings", "TamedDinoDamageMultiplier", s.TamedDinoDamageMultiplier); s.TamedDinoResistanceMultiplier = gus.GetFloat("ServerSettings", "TamedDinoResistanceMultiplier", s.TamedDinoResistanceMultiplier); s.MaxTamedDinos = gus.GetInt("ServerSettings", "MaxTamedDinos", s.MaxTamedDinos); s.GlobalSpoilingTimeMultiplier = gus.GetFloat("ServerSettings", "GlobalSpoilingTimeMultiplier", s.GlobalSpoilingTimeMultiplier); s.GlobalItemDecompositionTimeMultiplier = gus.GetFloat("ServerSettings", "GlobalItemDecompositionTimeMultiplier", s.GlobalItemDecompositionTimeMultiplier); s.DisableStructureDecayPvE = gus.GetBool("ServerSettings", "DisableStructureDecayPvE", s.DisableStructureDecayPvE); s.MaxNumberOfPlayersInTribe = gus.GetInt("ServerSettings", "MaxNumberOfPlayersInTribe", s.MaxNumberOfPlayersInTribe); // Mods s.ActiveMods = gus.Get("ModInstaller", "ModIDs", s.ActiveMods); // PerLevelStats from Game.ini var ps = s.PerLevelStats; bool hasPerLevel = false; for (int i = 0; i < 12; i++) { var pKey = $"PerLevelStatsMultiplier_Player[{i}]"; var dKey = $"PerLevelStatsMultiplier_DinoWild[{i}]"; var dtKey = $"PerLevelStatsMultiplier_DinoTamed[{i}]"; if (game.GetRaw("/script/shootergame.shootergamemode", pKey) is string pVal) { ps.Player[i] = ParseFloat(pVal); hasPerLevel = true; } if (game.GetRaw("/script/shootergame.shootergamemode", dKey) is string dVal) ps.DinoWild[i] = ParseFloat(dVal); if (game.GetRaw("/script/shootergame.shootergamemode", dtKey) is string dtVal) ps.DinoTamed[i] = ParseFloat(dtVal); } s.UseCustomPerLevelStats = hasPerLevel; return s; } public static PalworldServerSettings ImportPalworld(string iniContent) { var s = new PalworldServerSettings(); var rawLine = iniContent.Split('\n') .Select(l => l.Trim()) .FirstOrDefault(l => l.StartsWith("OptionSettings=(")); if (rawLine == null) return s; var inner = rawLine.Substring("OptionSettings=(".Length).TrimEnd(')'); foreach (var pair in SplitTopLevel(inner)) { var eq = pair.IndexOf('='); if (eq < 0) continue; var key = pair[..eq].Trim(); var val = pair[(eq + 1)..].Trim().Trim('"'); switch (key) { case "Difficulty": s.Difficulty = val; break; case "DayTimeSpeedRate": s.DayTimeSpeedRate = ParseFloat(val); break; case "NightTimeSpeedRate": s.NightTimeSpeedRate = ParseFloat(val); break; case "ExpRate": s.ExpRate = ParseFloat(val); break; case "PalCaptureRate": s.PalCaptureRate = ParseFloat(val); break; case "PalSpawnNumRate": s.PalSpawnNumRate = ParseFloat(val); break; case "PalDamageRateAttack": s.PalDamageRateAttack = ParseFloat(val); break; case "PalDamageRateDefense": s.PalDamageRateDefense = ParseFloat(val); break; case "PlayerDamageRateAttack": s.PlayerDamageRateAttack = ParseFloat(val); break; case "PlayerDamageRateDefense": s.PlayerDamageRateDefense = ParseFloat(val); break; case "EnemyDropItemRate": s.EnemyDropItemRate = ParseFloat(val); break; case "DeathPenalty": s.DeathPenalty = val; break; case "bIsPvP": s.bIsPvP = val == "True"; break; case "bEnablePlayerToPlayerDamage": s.bEnablePlayerToPlayerDamage = val == "True"; break; case "bEnableFriendlyFire": s.bEnableFriendlyFire = val == "True"; break; case "ServerName": s.ServerName = val; break; case "ServerDescription": s.ServerDescription = val; break; case "AdminPassword": s.AdminPassword = val; break; case "ServerPassword": s.ServerPassword = val; break; case "PublicPort": s.PublicPort = ParseInt(val); break; case "PublicIP": s.PublicIP = val; break; case "ServerPlayerMaxNum": s.ServerPlayerMaxNum = ParseInt(val); break; case "RCONEnabled": s.RCONEnabled = val == "True"; break; case "RCONPort": s.RCONPort = ParseInt(val); break; case "CollectionDropRate": s.CollectionDropRate = ParseFloat(val); break; case "CollectionObjectHpRate": s.CollectionObjectHpRate = ParseFloat(val); break; case "CollectionObjectRespawnSpeedRate": s.CollectionObjectRespawnSpeedRate = ParseFloat(val); break; case "BuildObjectDamageRate": s.BuildObjectDamageRate = ParseFloat(val); break; case "BuildObjectDeteriorationDamageRate": s.BuildObjectDeteriorationDamageRate = ParseFloat(val); break; case "BaseCampMaxNum": s.BaseCampMaxNum = ParseInt(val); break; case "BaseCampWorkerMaxNum": s.BaseCampWorkerMaxNum = ParseInt(val); break; case "DropItemMaxNum": s.DropItemMaxNum = ParseInt(val); break; case "bEnableFastTravel": s.bEnableFastTravel = val == "True"; break; case "bIsStartLocationSelectByMap": s.bIsStartLocationSelectByMap = val == "True"; break; case "bEnableNonLoginPenalty": s.bEnableNonLoginPenalty = val == "True"; break; case "bEnableInvaderEnemy": s.bEnableInvaderEnemy = val == "True"; break; case "bUseAuth": s.bUseAuth = val == "True"; break; case "BanListURL": s.BanListURL = val; break; } } return s; } private static IEnumerable SplitTopLevel(string s) { int depth = 0; int start = 0; for (int i = 0; i < s.Length; i++) { if (s[i] == '(') depth++; else if (s[i] == ')') depth--; else if (s[i] == ',' && depth == 0) { yield return s[start..i]; start = i + 1; } } if (start < s.Length) yield return s[start..]; } private static float ParseFloat(string v) => float.TryParse(v, NumberStyles.Float, CultureInfo.InvariantCulture, out var r) ? r : 0f; private static int ParseInt(string v) => int.TryParse(v, out var r) ? r : 0; private static IniData ParseIni(string content) { var data = new IniData(); string currentSection = ""; foreach (var rawLine in content.Split('\n')) { var line = rawLine.Trim(); if (string.IsNullOrEmpty(line) || line.StartsWith(';') || line.StartsWith('#')) continue; if (line.StartsWith('[') && line.EndsWith(']')) { currentSection = line[1..^1].ToLowerInvariant(); continue; } var eq = line.IndexOf('='); if (eq < 0) continue; var key = line[..eq].Trim(); var val = line[(eq + 1)..].Trim(); data.Set(currentSection, key, val); } return data; } private class IniData { private readonly Dictionary> _data = new(); public void Set(string section, string key, string value) { var s = section.ToLowerInvariant(); if (!_data.ContainsKey(s)) _data[s] = new Dictionary(StringComparer.OrdinalIgnoreCase); _data[s][key] = value; } public string? GetRaw(string section, string key) { var s = section.ToLowerInvariant(); return _data.TryGetValue(s, out var dict) && dict.TryGetValue(key, out var v) ? v : null; } public string Get(string section, string key, string def = "") => GetRaw(section, key) ?? def; public float GetFloat(string section, string key, float def = 0f) => float.TryParse(GetRaw(section, key), NumberStyles.Float, CultureInfo.InvariantCulture, out var r) ? r : def; public int GetInt(string section, string key, int def = 0) => int.TryParse(GetRaw(section, key), out var r) ? r : def; public bool GetBool(string section, string key, bool def = false) { var v = GetRaw(section, key); if (v == null) return def; return v.Equals("True", StringComparison.OrdinalIgnoreCase) || v == "1"; } } }