From 76eb86a425f70d4025df8b2203c9a2ae80172dd7 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Tue, 23 Sep 2025 03:54:00 +0200 Subject: [PATCH 01/33] this commit is a firstpass which addresses htps://github.com/SteamServerUI/StationeersServerUI/pull/94#discussion_r2368759050 by reworking the SaveInfo field into two seperate fields. Initial testing confirms desired functionality, though way more testing for backwards compatibility and general functionality (also in preterrain) is required to harden this. The localization also needs to be updated. --- .../onboard_bundled/twoboxform/twoboxform.js | 14 ++----- UIMod/onboard_bundled/ui/config.html | 14 ++++--- src/config/config.go | 40 ++++++++++++------- src/config/getters.go | 14 ++++--- src/config/setters.go | 16 ++++++++ src/config/vars.go | 4 +- src/core/loader/helpers.go | 6 +-- src/managers/backupmgr/backupinterface.go | 2 +- src/managers/gamemgr/args.go | 9 +++-- src/web/TwoBoxForm.go | 40 ++++++++++++------- src/web/configpage.go | 7 +++- src/web/templatevars.go | 6 +++ 12 files changed, 111 insertions(+), 61 deletions(-) diff --git a/UIMod/onboard_bundled/twoboxform/twoboxform.js b/UIMod/onboard_bundled/twoboxform/twoboxform.js index 57f2feb1..b8050c3e 100644 --- a/UIMod/onboard_bundled/twoboxform/twoboxform.js +++ b/UIMod/onboard_bundled/twoboxform/twoboxform.js @@ -136,28 +136,20 @@ document.addEventListener('DOMContentLoaded', () => { [configField]: booleanToConfig(document.getElementById('primary-field').value) }); - } else if (configField === "SaveInfo") { - const primaryValue = document.getElementById('primary-field').value.trim(); - // If the world name contains a space, it's invalid - if (primaryValue.includes(' ')) { - showNotification('The world name cannot contain spaces!', 'error'); - hidePreloader(); - return; // Prevent submission - } + } else if (configField === "WorldID") { const secondaryValue = document.getElementById('secondary-field').value.trim(); if (secondaryValue === '' || secondaryValue === document.getElementById('secondary-field').placeholder) { showNotification('Please select a world type!', 'error'); hidePreloader(); return; // Prevent submission } - const joinedValue = `${primaryValue} ${secondaryValue}`; body = JSON.stringify({ - [configField]: joinedValue + [configField]: secondaryValue }); } else if (configField === "gameBranch") { const secondaryValue = document.getElementById('secondary-field').value.trim(); if (secondaryValue === '' || secondaryValue === document.getElementById('secondary-field').placeholder) { - showNotification('Please select a world type!', 'error'); + showNotification('Please select a branch!', 'error'); hidePreloader(); return; // Prevent submission } diff --git a/UIMod/onboard_bundled/ui/config.html b/UIMod/onboard_bundled/ui/config.html index 64938633..9c82fe6c 100644 --- a/UIMod/onboard_bundled/ui/config.html +++ b/UIMod/onboard_bundled/ui/config.html @@ -76,11 +76,15 @@

{{.UIText_BasicServerSettings}}

- - -
{{.UIText_SaveFileNameInfo}}
-
{{.UIText_SaveFileNameUseWizzardButtonText}}
+ + +
{{.UIText_SaveNameInfo}}
+
+ +
+ + +
{{.UIText_WorldIDInfo}}
diff --git a/src/config/config.go b/src/config/config.go index f5c35304..a1c97c25 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -29,7 +29,9 @@ type JsonConfig struct { GameBranch string `json:"gameBranch"` GamePort string `json:"GamePort"` ServerName string `json:"ServerName"` - SaveInfo string `json:"SaveInfo"` + SaveInfo string `json:"SaveInfo"` // deprecated, kept for backwards compatibility + SaveName string `json:"SaveName"` // replaces SaveInfo + WorldID string `json:"WorldID"` // replaces SaveInfo ServerMaxPlayers string `json:"ServerMaxPlayers"` ServerPassword string `json:"ServerPassword"` ServerAuthSecret string `json:"ServerAuthSecret"` @@ -167,7 +169,9 @@ func applyConfig(cfg *JsonConfig) { StartCondition = getString(cfg.StartCondition, "START_CONDITION", "") StartLocation = getString(cfg.StartLocation, "START_LOCATION", "") ServerName = getString(cfg.ServerName, "SERVER_NAME", "Stationeers Server UI") - SaveInfo = getString(cfg.SaveInfo, "SAVE_INFO", "Vulcan Vulcan") + SaveInfo = getString(cfg.SaveInfo, "SAVE_INFO", "") + SaveName = getString(cfg.SaveName, "SAVE_NAME", "MyMapName") + WorldID = getString(cfg.WorldID, "WORLD_ID", "Lunar") ServerMaxPlayers = getString(cfg.ServerMaxPlayers, "SERVER_MAX_PLAYERS", "6") ServerPassword = getString(cfg.ServerPassword, "SERVER_PASSWORD", "") ServerAuthSecret = getString(cfg.ServerAuthSecret, "SERVER_AUTH_SECRET", "") @@ -202,7 +206,7 @@ func applyConfig(cfg *JsonConfig) { ServerVisible = serverVisibleVal cfg.ServerVisible = &serverVisibleVal - useSteamP2PVal := getBool(cfg.UseSteamP2P, "USE_STEAM_P2P", true) + useSteamP2PVal := getBool(cfg.UseSteamP2P, "USE_STEAM_P2P", false) UseSteamP2P = useSteamP2PVal cfg.UseSteamP2P = &useSteamP2PVal @@ -261,31 +265,37 @@ func applyConfig(cfg *JsonConfig) { AutoStartServerOnStartup = autoStartServerOnStartupVal cfg.AutoStartServerOnStartup = &autoStartServerOnStartupVal - // Process SaveInfo - parts := strings.Split(SaveInfo, " ") - if len(parts) > 0 { - WorldName = parts[0] - } - if len(parts) > 1 { - BackupWorldName = parts[1] + // Process SaveInfo to maintain backwards compatibility with pre-5.6.6 SaveInfo field (deprecated) + if SaveInfo != "" { + parts := strings.Split(SaveInfo, " ") + if len(parts) > 0 { + SaveName = parts[0] + fmt.Println("SaveName: " + SaveName) + } + if len(parts) > 1 { + WorldID = parts[1] + fmt.Println("WorldID: " + WorldID) + } } // Set backup paths for old or new style saves if IsNewTerrainAndSaveSystem { // use new new style autosave folder - ConfiguredBackupDir = filepath.Join("./saves/", WorldName, "autosave") + ConfiguredBackupDir = filepath.Join("./saves/", SaveName, "autosave") } else { // use old style Backups folder - ConfiguredBackupDir = filepath.Join("./saves/", WorldName, "Backup") + ConfiguredBackupDir = filepath.Join("./saves/", SaveName, "Backup") } // use Safebackups folder either way. - ConfiguredSafeBackupDir = filepath.Join("./saves/", WorldName, "Safebackups") + ConfiguredSafeBackupDir = filepath.Join("./saves/", SaveName, "Safebackups") + + safeSaveConfig() } // use safeSaveConfig EXCLUSIVELY though setter functions // M U S T be called while holding a lock on ConfigMu! func safeSaveConfig() error { - + fmt.Println("safeSaveConfig") cfg := JsonConfig{ DiscordToken: DiscordToken, ControlChannelID: ControlChannelID, @@ -312,6 +322,8 @@ func safeSaveConfig() error { StartLocation: StartLocation, ServerName: ServerName, SaveInfo: SaveInfo, + SaveName: SaveName, + WorldID: WorldID, ServerMaxPlayers: ServerMaxPlayers, ServerPassword: ServerPassword, ServerAuthSecret: ServerAuthSecret, diff --git a/src/config/getters.go b/src/config/getters.go index e1683922..27067b83 100644 --- a/src/config/getters.go +++ b/src/config/getters.go @@ -145,22 +145,24 @@ func GetServerName() string { return ServerName } -func GetSaveInfo() string { +// special getter for backwards compatibility with SaveInfo +func GetLegacySaveInfo() string { ConfigMu.RLock() defer ConfigMu.RUnlock() - return SaveInfo + saveinfo := SaveName + ";" + WorldID + return saveinfo } -func GetWorldName() string { +func GetSaveName() string { ConfigMu.RLock() defer ConfigMu.RUnlock() - return WorldName + return SaveName } -func GetBackupWorldName() string { +func GetWorldID() string { ConfigMu.RLock() defer ConfigMu.RUnlock() - return BackupWorldName + return WorldID } func GetServerMaxPlayers() string { diff --git a/src/config/setters.go b/src/config/setters.go index 9928d5cc..58627abb 100644 --- a/src/config/setters.go +++ b/src/config/setters.go @@ -70,6 +70,22 @@ func SetNoSanityCheck(value bool) error { return nil } +func SetSaveName(value string) error { + ConfigMu.Lock() + defer ConfigMu.Unlock() + + SaveName = value + return nil +} + +func SetWorldID(value string) error { + ConfigMu.Lock() + defer ConfigMu.Unlock() + + WorldID = value + return nil +} + // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT // ALL SETTERS BELOW THIS LINE ARE UNUSED AT THE MOMENT diff --git a/src/config/vars.go b/src/config/vars.go index edcb3c1d..a2f3a507 100644 --- a/src/config/vars.go +++ b/src/config/vars.go @@ -32,9 +32,9 @@ var ( AdditionalParams string UPNPEnabled bool StartLocalHost bool - WorldName string - BackupWorldName string SaveInfo string + SaveName string + WorldID string SaveInterval string AutoPauseServer bool AutoSave bool diff --git a/src/core/loader/helpers.go b/src/core/loader/helpers.go index 2c636319..fccb5e1b 100644 --- a/src/core/loader/helpers.go +++ b/src/core/loader/helpers.go @@ -50,8 +50,8 @@ func PrintConfigDetails(logLevel ...string) { server := map[string]string{ "GameBranch": config.GetGameBranch(), "ServerName": config.GetServerName(), - "WorldName": config.GetWorldName(), - "BackupWorldName": config.GetBackupWorldName(), + "WorldName": config.GetSaveName(), + "BackupWorldName": config.GetWorldID(), "ServerMaxPlayers": config.GetServerMaxPlayers(), "GamePort": config.GetGamePort(), "UpdatePort": config.GetUpdatePort(), @@ -69,7 +69,7 @@ func PrintConfigDetails(logLevel ...string) { "Difficulty": config.GetDifficulty(), "StartCondition": config.GetStartCondition(), "StartLocation": config.GetStartLocation(), - "SaveInfo": config.GetSaveInfo(), + "SaveInfo": config.GetLegacySaveInfo(), "IsNewTerrainAndSaveSystem": fmt.Sprintf("%v", config.GetIsNewTerrainAndSaveSystem()), } printSection("Server Configuration", server) diff --git a/src/managers/backupmgr/backupinterface.go b/src/managers/backupmgr/backupinterface.go index d2c99036..af8d857f 100644 --- a/src/managers/backupmgr/backupinterface.go +++ b/src/managers/backupmgr/backupinterface.go @@ -47,7 +47,7 @@ func RegisterHTTPHandler(handler *HTTPHandler) { func GetBackupConfig() BackupConfig { return BackupConfig{ - WorldName: config.GetWorldName(), + WorldName: config.GetSaveName(), BackupDir: config.GetConfiguredBackupDir(), SafeBackupDir: config.GetConfiguredSafeBackupDir(), WaitTime: 30 * time.Second, // not sure why we are not using config.BackupWaitTime here, but ill not touch it in this commit (config rework) diff --git a/src/managers/gamemgr/args.go b/src/managers/gamemgr/args.go index 8b0bff6f..3ccba137 100644 --- a/src/managers/gamemgr/args.go +++ b/src/managers/gamemgr/args.go @@ -30,8 +30,8 @@ func buildCommandArgs() []string { -startlocation (Optional, defaults to "DefaultStartLocation" if not provided.) */ {Flag: "-file", RequiresValue: false}, - {Flag: "start", Value: config.GetWorldName(), RequiresValue: true}, - {Flag: config.GetBackupWorldName(), RequiresValue: false}, + {Flag: "start", Value: config.GetSaveName(), RequiresValue: true}, + {Flag: config.GetWorldID(), RequiresValue: false}, {Flag: config.GetDifficulty(), RequiresValue: false, Condition: func() bool { return config.GetDifficulty() != "" }}, {Flag: config.GetStartCondition(), RequiresValue: false, Condition: func() bool { return config.GetStartCondition() != "" }}, {Flag: config.GetStartLocation(), RequiresValue: false, Condition: func() bool { return config.GetStartLocation() != "" }}, @@ -58,7 +58,7 @@ func buildCommandArgs() []string { argOrder = []Arg{ {Flag: "-nographics", RequiresValue: false}, {Flag: "-batchmode", RequiresValue: false}, - {Flag: "-LOAD", Value: config.GetSaveInfo(), RequiresValue: true, NoQuote: true}, // LOAD has special handling because the gameserver expects 2 parameters + {Flag: "-LOAD", Value: config.GetLegacySaveInfo(), RequiresValue: true, NoQuote: true}, // LOAD has special handling because the gameserver expects 2 parameters {Flag: "-logFile", Value: "./debug.log", Condition: func() bool { return runtime.GOOS == "linux" }, RequiresValue: true}, {Flag: "-settings", RequiresValue: false}, {Flag: "StartLocalHost", Value: strconv.FormatBool(config.GetStartLocalHost()), RequiresValue: true}, @@ -89,8 +89,9 @@ func buildCommandArgs() []string { args = append(args, arg.Flag) + // handling of Legacy SaveInfo: Split on semicolon and add each part as a separate arg. This is a hack to continue to support the old saveinfo format for preterrain servers. if arg.Flag == "-LOAD" && arg.Value != "" { - parts := strings.SplitN(arg.Value, " ", 2) + parts := strings.SplitN(arg.Value, ";", 2) for _, part := range parts { if part != "" { args = append(args, part) diff --git a/src/web/TwoBoxForm.go b/src/web/TwoBoxForm.go index 76695b3e..55073b07 100644 --- a/src/web/TwoBoxForm.go +++ b/src/web/TwoBoxForm.go @@ -171,22 +171,34 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { SubmitButtonText: localization.GetString("UIText_ServerName_SubmitButton"), SkipButtonText: localization.GetString("UIText_ServerName_SkipButton"), ConfigField: "ServerName", - NextStep: "save_identifier", + NextStep: "save_name", }, - "save_identifier": { - ID: "save_identifier", - Title: localization.GetString("UIText_SaveIdentifier_Title"), - HeaderTitle: localization.GetString("UIText_SaveIdentifier_HeaderTitle"), - StepMessage: localization.GetString("UIText_SaveIdentifier_StepMessage"), - PrimaryPlaceholderText: localization.GetString("UIText_SaveIdentifier_PrimaryPlaceholder"), - PrimaryLabel: localization.GetString("UIText_SaveIdentifier_PrimaryLabel"), - SecondaryLabel: localization.GetString("UIText_SaveIdentifier_SecondaryLabel"), + "save_name": { + ID: "save_name", + Title: localization.GetString("UIText_SaveName_Title"), + HeaderTitle: localization.GetString("UIText_SaveName_HeaderTitle"), + StepMessage: localization.GetString("UIText_SaveName_StepMessage"), + PrimaryPlaceholderText: localization.GetString("UIText_SaveName_PrimaryPlaceholder"), + PrimaryLabel: localization.GetString("UIText_SaveName_PrimaryLabel"), + SecondaryLabel: "", + SecondaryLabelType: "hidden", + SubmitButtonText: localization.GetString("UIText_SaveName_SubmitButton"), + SkipButtonText: localization.GetString("UIText_SaveName_SkipButton"), + ConfigField: "SaveName", + NextStep: "world_id", + }, + "world_id": { + ID: "world_id", + Title: localization.GetString("UIText_WorldID_Title"), + HeaderTitle: localization.GetString("UIText_WorldID_HeaderTitle"), + StepMessage: localization.GetString("UIText_WorldID_StepMessage"), + SecondaryLabel: localization.GetString("UIText_WorldID_SecondaryLabel"), SecondaryLabelType: "dropdown", - SecondaryPlaceholderText: localization.GetString("UIText_SaveIdentifier_SecondaryPlaceholder"), + SecondaryPlaceholderText: localization.GetString("UIText_WorldID_SecondaryPlaceholder"), SecondaryOptions: worldOptions, - SubmitButtonText: localization.GetString("UIText_SaveIdentifier_SubmitButton"), - SkipButtonText: localization.GetString("UIText_SaveIdentifier_SkipButton"), - ConfigField: "SaveInfo", + SubmitButtonText: localization.GetString("UIText_WorldID_SubmitButton"), + SkipButtonText: localization.GetString("UIText_WorldID_SkipButton"), + ConfigField: "WorldID", NextStep: "max_players", }, "max_players": { @@ -366,7 +378,7 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { data.Step = "welcome" } stepOrder := []string{ - "welcome", "pls_read", "game_branch", "newterrain_and_savesystem", "server_name", "save_identifier", "max_players", + "welcome", "pls_read", "game_branch", "newterrain_and_savesystem", "server_name", "save_name", "world_id", "max_players", "server_password", "discord_enabled", "discord_token", "control_panel_channel", "save_channel", "log_channel", "connection_list_channel", "status_channel", "control_channel", diff --git a/src/web/configpage.go b/src/web/configpage.go index 41853a2b..1a90205a 100644 --- a/src/web/configpage.go +++ b/src/web/configpage.go @@ -127,7 +127,8 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) { StartCondition: config.GetStartCondition(), StartLocation: config.GetStartLocation(), ServerName: config.GetServerName(), - SaveInfo: config.GetSaveInfo(), + SaveInfo: config.GetLegacySaveInfo(), + WorldID: config.GetWorldID(), ServerMaxPlayers: config.GetServerMaxPlayers(), ServerPassword: config.GetServerPassword(), ServerAuthSecret: config.GetServerAuthSecret(), @@ -185,6 +186,10 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) { UIText_SaveFileName: localization.GetString("UIText_SaveFileName"), UIText_SaveFileNameInfo: localization.GetString("UIText_SaveFileNameInfo"), UIText_SaveFileNameUseWizzardButtonText: localization.GetString("UIText_SaveFileNameUseWizzardButtonText"), + UIText_SaveName: localization.GetString("UIText_SaveName"), + UIText_SaveNameInfo: localization.GetString("UIText_SaveNameInfo"), + UIText_WorldID: localization.GetString("UIText_WorldID"), + UIText_WorldIDInfo: localization.GetString("UIText_WorldIDInfo"), UIText_MaxPlayers: localization.GetString("UIText_MaxPlayers"), UIText_MaxPlayersInfo: localization.GetString("UIText_MaxPlayersInfo"), UIText_ServerPassword: localization.GetString("UIText_ServerPassword"), diff --git a/src/web/templatevars.go b/src/web/templatevars.go index f0281fff..20f21394 100644 --- a/src/web/templatevars.go +++ b/src/web/templatevars.go @@ -41,6 +41,8 @@ type ConfigTemplateData struct { StartLocation string ServerName string SaveInfo string + SaveName string + WorldID string ServerMaxPlayers string ServerPassword string ServerAuthSecret string @@ -97,6 +99,10 @@ type ConfigTemplateData struct { UIText_SaveFileName string UIText_SaveFileNameInfo string UIText_SaveFileNameUseWizzardButtonText string + UIText_SaveName string + UIText_SaveNameInfo string + UIText_WorldID string + UIText_WorldIDInfo string UIText_MaxPlayers string UIText_MaxPlayersInfo string UIText_ServerPassword string From 0197a9b50edb649bd870ad64b42187cdb808eb8c Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Wed, 24 Sep 2025 02:28:11 +0200 Subject: [PATCH 02/33] added missing SaveName template var to config page --- src/web/configpage.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/web/configpage.go b/src/web/configpage.go index 1a90205a..90340314 100644 --- a/src/web/configpage.go +++ b/src/web/configpage.go @@ -127,6 +127,7 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) { StartCondition: config.GetStartCondition(), StartLocation: config.GetStartLocation(), ServerName: config.GetServerName(), + SaveName: config.GetSaveName(), SaveInfo: config.GetLegacySaveInfo(), WorldID: config.GetWorldID(), ServerMaxPlayers: config.GetServerMaxPlayers(), From 2bfaf75e4b0f7526c7a315d56102a3701324806b Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Wed, 24 Sep 2025 14:10:35 +0200 Subject: [PATCH 03/33] re-added weblate generated current localization files --- UIMod/onboard_bundled/localization/de-DE.json | 501 ++++++++--------- UIMod/onboard_bundled/localization/en-US.json | 508 +++++++++--------- UIMod/onboard_bundled/localization/sv-SE.json | 499 ++++++++--------- 3 files changed, 758 insertions(+), 750 deletions(-) diff --git a/UIMod/onboard_bundled/localization/de-DE.json b/UIMod/onboard_bundled/localization/de-DE.json index eb1f2454..ad594471 100644 --- a/UIMod/onboard_bundled/localization/de-DE.json +++ b/UIMod/onboard_bundled/localization/de-DE.json @@ -1,250 +1,257 @@ { - "UIText": { - "index": { - "UIText_StartButton": "Server starten", - "UIText_StopButton": "Server stoppen", - "UIText_Settings": "Optionen", - "UIText_Update_SteamCMD": "Server Updaten", - "UIText_Console": "Konsole", - "UIText_Detection_Events": "Ereignisse", - "UIText_Backend_Log": "Backend Konsole", - "UIText_Backup_Manager": "Spielstands-Manager", - "UIText_Connected_PlayersHeader": "Verbundene Spieler", - "UIText_Discord_Info": "Tritt dem Discord bei und hilf uns SSUI besser zu machen oder Support anzufragen!", - "UIText_API_Info": "API-Endpunktdokumentation", - "UIText_Copyright": "Urheberrecht", - "UIText_Copyright1": "Lizenziert unter", - "UIText_Copyright2": "Proprietärer Lizenz." + "UIText": { + "index": { + "UIText_StartButton": "Server starten", + "UIText_StopButton": "Server stoppen", + "UIText_Settings": "Optionen", + "UIText_Update_SteamCMD": "Server Updaten", + "UIText_Console": "Konsole", + "UIText_Detection_Events": "Ereignisse", + "UIText_Backend_Log": "Backend Konsole", + "UIText_Backup_Manager": "Spielstands-Manager", + "UIText_Connected_PlayersHeader": "Verbundene Spieler", + "UIText_Discord_Info": "Tritt dem Discord bei und hilf uns SSUI besser zu machen oder Support anzufragen!", + "UIText_API_Info": "API-Endpunktdokumentation", + "UIText_Copyright": "Urheberrecht", + "UIText_Copyright1": "Lizenziert unter", + "UIText_Copyright2": "Proprietärer Lizenz" + }, + "config": { + "UIText_ServerConfig": "Server Konfiguration", + "UIText_DiscordIntegration": "Discord-Integration", + "UIText_DetectionManager": "Erkennungsmanager", + "UIText_ConfigurationWizard": "Konfigurations-Assistent", + "UIText_PleaseSelectSection": "Bitte wähle oben eine Konfigurationssektion aus", + "UIText_UseWizardAlternative": "Alternativ nutze den Konfigurations-Assistenten zur Serverkonfiguration.", + "UIText_BasicSettings": "Basis", + "UIText_NetworkSettings": "Netzwerk", + "UIText_AdvancedSettings": "Erweitert", + "basic": { + "UIText_BasicServerSettings": "Grundlegende Servereinstellungen", + "UIText_ServerName": "Servername", + "UIText_ServerNameInfo": "Name in der Serverliste angezeigt", + "UIText_SaveFileName": "Speicherdatei Name", + "UIText_SaveFileNameInfo": "Name des Speicherordners. Muss großgeschrieben sein. Für neue Welt, Welttyp angeben. Es wird empfohlen, diesen Wert über den Setup Assistent zu konfigurieren um ihn korrekt zu setzen. ", + "UIText_SaveFileNameUseWizzardButtonText": "Öffne Assistent", + "UIText_MaxPlayers": "Max Spieler", + "UIText_MaxPlayersInfo": "Maximale Anzahl erlaubter Spieler", + "UIText_ServerPassword": "Server Passwort", + "UIText_ServerPasswordInfo": "Leer lassen für kein Passwort", + "UIText_AdminPassword": "Admin Passwort", + "UIText_AdminPasswordInfo": "Server Admin Passwort", + "UIText_AutoSave": "Auto Speichern", + "UIText_AutoSaveInfo": "Auf TRUE setzen für automatisches Speichern", + "UIText_SaveInterval": "Speicher Intervall", + "UIText_SaveIntervalInfo": "Zeit in Sekunden zwischen Speichervorgängen. Sollte 60 Sekunden nicht unterschreiten.", + "UIText_AutoPauseServer": "Server Auto Pausieren", + "UIText_AutoPauseServerInfo": "Server automatisch pausieren wenn keine Spieler verbunden" + }, + "network": { + "UIText_NetworkConfiguration": "Netzwerk Konfiguration", + "UIText_GamePort": "Spiel Port", + "UIText_GamePortInfo": "Standard: 27016", + "UIText_UpdatePort": "Update Port", + "UIText_UpdatePortInfo": "Standard: 27015", + "UIText_UPNPEnabled": "UPNP Aktiviert", + "UIText_UPNPEnabledInfo": "Automatische UPNP Portweiterleitung aktivieren", + "UIText_LocalIpAddress": "Lokale IP Adresse", + "UIText_LocalIpAddressInfo": "IP Adresse zum Binden", + "UIText_StartLocalHost": "Lokalen Host Starten", + "UIText_StartLocalHostInfo": "Auf TRUE setzen. Dies ist erforderlich für den Server um zu funktionieren.", + "UIText_ServerVisible": "Server Sichtbar", + "UIText_ServerVisibleInfo": "Auf TRUE setzen um Server öffentlich zu listen", + "UIText_UseSteamP2P": "Steam P2P Nutzen", + "UIText_UseSteamP2PInfo": "Steam Peer-to-Peer Netzwerk aktivieren" + }, + "advanced": { + "UIText_AdvancedConfiguration": "Erweiterte Konfiguration", + "UIText_ServerAuthSecret": "Server Auth Geheimnis", + "UIText_ServerAuthSecretInfo": "Authentifizierungsgeheimnis für Server (optional)", + "UIText_ServerExePath": "Server Ausführungspfad", + "UIText_ServerExePathInfo": "Systempfad zur Server-Anwendung", + "UIText_ServerExePathInfo2": "Aus Sicherheitsgründen nicht über UI editierbar, aber manuell in config.json änderbar.", + "UIText_AdditionalParams": "Zusätzliche Parameter", + "UIText_AdditionalParamsInfo": "Format: EigenParam1 Wert1 EigenParam2 Wert2", + "UIText_AutoRestartServerTimer": "Geplanter Gameserver Neustart", + "UIText_AutoRestartServerTimerInfo": "

Zeitraum in Minuten oder Zeitformat (z. B. 15:04 oder 03:04 Uhr) um einen automatischen Neustart des Spielservers zu planen. 0 = deaktiviert, 1440 = 24 Stunden usw. Vor dem Neustart wird die Meldung „Achtung, der Server wird in 30/20/10/5 Sekunden neu gestartet!“ angezeigt im Spiel.

", + "UIText_GameBranch": "Spiel Branch", + "UIText_GameBranchInfo": "Branch des Spiels. Bei Änderung SSUI Neustart erforderlich!", + "UIText_AllowAutoGameServerUpdates": "Automatische Game Server updates einschalten", + "UIText_AllowAutoGameServerUpdatesInfo": "Erlaubt dem Spielserver, automatisch nach der neuesten Version zu suchen und diese zu installieren. Achtung: Der Server wird neu gestartet, wenn eine neue Version gefunden und installiert wurde. 60 bis 10 Sekunden vor dem Neustart werden mehrere Warnmeldungen mit SAY-Befehlen an den Server gesendet." + }, + "terrain": { + "UIText_Difficulty": "Schwierigkeit", + "UIText_DifficultyInfo": "Schwierigkeit für Welterstellung. Standard Normal wenn leer.", + "UIText_StartCondition": "Startbedingung", + "UIText_StartConditionInfo": "Startbedingung für Welterstellung. Standard-Startbedingung für Welttyp wenn leer.", + "UIText_StartLocation": "Startort", + "UIText_StartLocationInfo": "Startort für Welterstellung. Standard DefaultStartLocation wenn leer.", + "UIText_AutoStartServerOnStartup": "Server Auto-Start beim Hochfahren", + "UIText_AutoStartServerOnStartupInfo": "Gameserver automatisch starten wenn SSUI gestartet wird. Standard false.", + "UIText_AllowAutoGameServerUpdates": "Automatische Spielserver-Updates aktivieren", + "UIText_AllowAutoGameServerUpdatesInfo": "Erlaubt dem Spielserver, automatisch nach der neuesten Version zu suchen und diese zu installieren. Achtung: Der Server wird neu gestartet, wenn eine neue Version gefunden und installiert wurde. 60 bis 10 Sekunden vor dem Neustart werden mehrere Warnmeldungen mit SAY-Befehlen an den Server gesendet.", + "UIText_TerrainSettingsHeader": "Neues Terrain und Speicher System Einstellungen", + "UIText_TerrainWarning": "Diese Einstellungen sind nur nützlich, wenn Sie eine Stationeers-Version verwenden, die NEUER als September 2025 ist. Alte Spielstände sind NICHT mit dem neuen System kompatibel, können aber mit JacksonTheMasters Migrationstool migriert werden. Die entsprechenden „How-to”-Informationen in den FAQ gelten auch für den dedizierten Server.", + "UIText_UseNewTerrainAndSave": "Neues Terrain und Save System verwenden", + "UIText_UseNewTerrainAndSaveInfo": "Setzen Sie diesen Wert auf TRUE, um die Verarbeitung von .save-Dateien im Backup-Manager und die Argumentanalyse zu aktivieren. Wenn dieser Wert auf FALSE gesetzt ist, funktionieren nur Stationeers-Versionen vor der Überarbeitung des Terrains (≈ Mitte 2025). Der Standardwert ist TRUE!" + }, + "discord": { + "UIText_DiscordIntegrationTitle": "Discord Integration Vorteile", + "UIText_DiscordBotToken": "Discord-Bot-Token", + "UIText_DiscordBotTokenInfo": "Authentifizierungstoken deines Discord Bots", + "UIText_ChannelConfiguration": "Channel Konfiguration", + "UIText_AdminCommandChannel": "Admin-Befehlskanal", + "UIText_AdminCommandChannelInfo": "Channel für Admin-Befehle", + "UIText_ControlPanelChannel": "Kontrollpanel Channel", + "UIText_ControlPanelChannelInfo": "Channel für Kontrollpanel", + "UIText_StatusChannel": "Statuskanal", + "UIText_StatusChannelInfo": "Server Status Updates", + "UIText_ConnectionListChannel": "Verbindungslisten Channel", + "UIText_ConnectionListChannelInfo": "Spielerverbindungs-Tracking", + "UIText_LogChannel": "Protokollkanal", + "UIText_LogChannelInfo": "Server Log Ausgabe", + "UIText_SaveInfoChannel": "Speicherinfo Channel", + "UIText_SaveInfoChannelInfo": "Speicherdatei Informationen", + "UIText_ErrorChannel": "Fehler Channel", + "UIText_ErrorChannelInfo": "Server Fehlermeldungen", + "UIText_BannedPlayersListPath": "Gesperrte Spieler Liste Pfad", + "UIText_BannedPlayersListPathInfo": "Dateipfad zur gesperrten Spieler Liste", + "UIText_DiscordIntegrationBenefits": "Discord Integration Vorteile", + "UIText_DiscordBenefit1": "Server Status in Echtzeit überwachen", + "UIText_DiscordBenefit2": "Neustarts und Wiederherstellungen remote verwalten", + "UIText_DiscordBenefit3": "Spielerverbindungen verfolgen", + "UIText_DiscordBenefit4": "Community-Management Optionen", + "UIText_DiscordBenefit5": "Echtzeit Fehlerbenachrichtigungen", + "UIText_DiscordSetupInstructions": "Für Setup-Anweisungen besuche die" + }, + "UIText_TerrainSettings": "Neues Gelände" + }, + "setup": { + "UIText_FooterText": "Hilfe benötigt? Schaue ins Stationeers Server UI Github Wiki.", + "UIText_FooterTextInfo": "Du kannst das Setup jederzeit beenden, jeder Schritt wird einzeln gespeichert.", + "UIText_SSCM_FooterText": "Nutze SSCM für das mächtigste Stationeers Server Management! Du kannst Befehle von der Web-Konsole ausführen ohne Vanilla-Verhalten zu stören!", + "UIText_Welcome_Title": "Stationeers Server UI", + "UIText_Welcome_HeaderTitle": "Willkommen!", + "UIText_Welcome_SubmitButton": "Setup Starten", + "UIText_Welcome_SkipButton": "Setup Überspringen", + "UIText_PlsRead_Title": "Bitte lesen!", + "UIText_PlsRead_HeaderTitle": "Hinweis", + "UIText_PlsRead_StepMessage": "Wir empfehlen stark, die Texte in diesem Setup-Assistenten zu lesen! Die meisten gemeldeten Probleme entstehen durch Fehlkonfiguration.", + "UIText_PlsRead_SubmitButton": "Verstanden", + "UIText_PlsRead_SkipButton": "Verstanden", + "UIText_ServerName_Title": "Stationeers Server UI", + "UIText_ServerName_HeaderTitle": "Servername", + "UIText_ServerName_StepMessage": "Gib deinem Server einen Namen wie 'Weltraumstation 13'", + "UIText_ServerName_PrimaryPlaceholder": "Mein Stationeers Server mit UI", + "UIText_ServerName_PrimaryLabel": "Servername", + "UIText_ServerName_SubmitButton": "Speichern & Weiter", + "UIText_ServerName_SkipButton": "Überspringen", + "UIText_SaveIdentifier_Title": "Stationeers Server UI", + "UIText_SaveIdentifier_HeaderTitle": "Speicherstand", + "UIText_SaveIdentifier_StepMessage": "Konfiguriere unten den Namen deines Speicherstands und den Welttyp.", + "UIText_SaveIdentifier_PrimaryLabel": "Name deiner Karte", + "UIText_SaveIdentifier_PrimaryPlaceholder": "MeineStationeersKarte", + "UIText_SaveIdentifier_SecondaryLabel": "Stationeers-Welttyp", + "UIText_SaveIdentifier_SecondaryPlaceholder": "Klicke, um einen Welttyp auszuwählen", + "UIText_SaveIdentifier_SubmitButton": "Speichern & Weiter", + "UIText_SaveIdentifier_SkipButton": "Überspringen", + "UIText_MaxPlayers_Title": "Stationeers Server UI", + "UIText_MaxPlayers_HeaderTitle": "Spielerlimit", + "UIText_MaxPlayers_StepMessage": "Wähle die maximale Anzahl an Spielern, die sich mit dem Server verbinden können. Es wird empfohlen, 20 nicht zu überschreiten", + "UIText_MaxPlayers_PrimaryPlaceholder": "8", + "UIText_MaxPlayers_PrimaryLabel": "Max Spieler", + "UIText_MaxPlayers_SubmitButton": "Speichern & Weiter", + "UIText_MaxPlayers_SkipButton": "Überspringen", + "UIText_ServerPassword_Title": "Stationeers Server UI", + "UIText_ServerPassword_HeaderTitle": "Server Passwort", + "UIText_ServerPassword_StepMessage": "Setze ein Gameserver Passwort oder überspringe diesen Schritt.", + "UIText_ServerPassword_PrimaryPlaceholder": "Server Passwort", + "UIText_ServerPassword_PrimaryLabel": "Server Passwort", + "UIText_ServerPassword_SubmitButton": "Speichern & Weiter", + "UIText_ServerPassword_SkipButton": "Überspringen", + "UIText_GameBranch_Title": "Stationeers Server UI", + "UIText_GameBranch_HeaderTitle": "Spiel Branch", + "UIText_GameBranch_StepMessage": "Gib einen Beta-Branch ein oder überspringe für Release-Version. Wenn Sie den Branch wechseln, klicken Sie nach Abschluss dieses Assistenten unbedingt auf „Server aktualisieren“ im Haupt-Dashboard.", + "UIText_GameBranch_SecondaryPlaceholder": "Wähle einen Branch", + "UIText_GameBranch_SecondaryLabel": "Spiel Branch", + "UIText_GameBranch_SubmitButton": "Speichern & Weiter", + "UIText_GameBranch_SkipButton": "Release Version nutzen", + "UIText_NewTerrainAndSaveSystem_Title": "Wichtig", + "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Terrainsystem wählen", + "UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder": "nein", + "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Neues System aktivieren", + "UIText_NewTerrainAndSaveSystem_SubmitButton": "Speichern & Weiter", + "UIText_NewTerrainAndSaveSystem_SkipButton": "Überspringen", + "UIText_NetworkConfigChoice_Title": "Stationeers Server UI", + "UIText_NetworkConfigChoice_HeaderTitle": "Netzwerk Konfiguration", + "UIText_NetworkConfigChoice_StepMessage": "Netzwerkeinstellungen konfigurieren? 'ja' für Konfiguration oder Überspringen für Standards. Hinweis: Netzwerkkonfiguration besonders wichtig auf Linux Servern.", + "UIText_NetworkConfigChoice_PrimaryPlaceholder": "ja", + "UIText_NetworkConfigChoice_PrimaryLabel": "Netzwerk Konfigurieren", + "UIText_NetworkConfigChoice_SubmitButton": "Weiter", + "UIText_NetworkConfigChoice_SkipButton": "Überspringen (Standards nutzen)", + "UIText_GamePort_Title": "Stationeers Server UI", + "UIText_GamePort_HeaderTitle": "Netzwerk (1/4)", + "UIText_GamePort_StepMessage": "Port-Nummer für Spielverbindungen eingeben", + "UIText_GamePort_PrimaryPlaceholder": "27016", + "UIText_GamePort_PrimaryLabel": "Spiel Port", + "UIText_GamePort_SubmitButton": "Speichern & Weiter", + "UIText_GamePort_SkipButton": "Überspringen", + "UIText_UpdatePort_Title": "Stationeers Server UI", + "UIText_UpdatePort_HeaderTitle": "Netzwerk (2/4)", + "UIText_UpdatePort_StepMessage": "Port-Nummer für Update-Verbindungen eingeben", + "UIText_UpdatePort_PrimaryPlaceholder": "27015", + "UIText_UpdatePort_PrimaryLabel": "Update Port", + "UIText_UpdatePort_SubmitButton": "Speichern & Weiter", + "UIText_UpdatePort_SkipButton": "Überspringen", + "UIText_UPnPEnabled_Title": "Stationeers Server UI", + "UIText_UPnPEnabled_HeaderTitle": "Netzwerk (3/4)", + "UIText_UPnPEnabled_StepMessage": "UPnP aktivieren? 'ja' zum Aktivieren oder 'nein' zum Deaktivieren.", + "UIText_UPnPEnabled_PrimaryPlaceholder": "ja/nein", + "UIText_UPnPEnabled_PrimaryLabel": "UPnP Aktivieren", + "UIText_UPnPEnabled_SubmitButton": "Speichern & Weiter", + "UIText_UPnPEnabled_SkipButton": "Überspringen", + "UIText_LocalIPAddress_Title": "Stationeers Server UI", + "UIText_LocalIPAddress_HeaderTitle": "Netzwerk (4/4)", + "UIText_LocalIPAddress_StepMessage": "Lokale IP-Adresse des Servers im Format 0.0.0.0 eingeben (keine CIDR Notation)", + "UIText_LocalIPAddress_PrimaryPlaceholder": "0.0.0.0", + "UIText_LocalIPAddress_PrimaryLabel": "Lokale IP-Adresse", + "UIText_LocalIPAddress_SubmitButton": "Speichern & Weiter", + "UIText_LocalIPAddress_SkipButton": "Überspringen", + "UIText_AdminAccount_Title": "Stationeers Server UI", + "UIText_AdminAccount_HeaderTitle": "Adminkonto", + "UIText_AdminAccount_StepMessage": "Richte dein Adminkonto ein.", + "UIText_AdminAccount_PrimaryPlaceholder": "Benutzername", + "UIText_AdminAccount_PrimaryLabel": "Benutzername", + "UIText_AdminAccount_SecondaryLabel": "Passwort", + "UIText_AdminAccount_SecondaryPlaceholder": "Passwort", + "UIText_AdminAccount_SubmitButton": "Speichern & Weiter", + "UIText_AdminAccount_SkipButton": "Authentifizierung Überspringen", + "UIText_Finalize_Title": "Du hast es geschafft", + "UIText_Finalize_HeaderTitle": "Setup Abschließen", + "UIText_Finalize_StepMessage": "Bereit zum Abschließen? Deine Konfiguration wurde bereits während des Setups gespeichert. Für Änderungen klicke 'Zurück zum Start' und überspringe was behalten werden soll. Meiste Optionen auch im Config Tab änderbar.", + "UIText_Finalize_SubmitButton": "Zurück zum Start", + "UIText_Finalize_SkipButton": "Authentifizierung Überspringen", + "UIText_Login_Title": "Stationeers Server UI", + "UIText_Login_HeaderTitle": "Login", + "UIText_Login_PrimaryLabel": "Benutzername", + "UIText_Login_SecondaryLabel": "Passwort", + "UIText_Login_PrimaryPlaceholder": "Benutzername eingeben", + "UIText_Login_SecondaryPlaceholder": "Passwort eingeben", + "UIText_Login_SubmitButton": "Anmelden", + "UIText_ChangeUser_Title": "Stationeers Server UI", + "UIText_ChangeUser_HeaderTitle": "Benutzer Verwalten", + "UIText_ChangeUser_PrimaryLabel": "Benutzername Hinzufügen/Aktualisieren", + "UIText_ChangeUser_SecondaryLabel": "Neues Passwort", + "UIText_ChangeUser_SecondaryPlaceholder": "Passwort", + "UIText_ChangeUser_SubmitButton": "Benutzer Hinzufügen/Aktualisieren", + "UIText_NewTerrainAndSaveSystem_StepMessage": "Verwenden Sie einen ALTEN Branch, wie z. B. preterrain oder älter, ohne die Änderungen am Geländesystem? Wenn ja, deaktivieren Sie hier die Verarbeitung des neuen Geländes und Speichersystems. Geben Sie „yes” ein oder überspringen Sie diesen Schritt, um die Funktion zu aktivieren (Standard), oder „no”, um das alte Speicher- und Geländesystem zu verwenden. Wenn Sie sich nicht sicher sind, überspringen Sie diesen Schritt." + } }, - "config": { - "UIText_ServerConfig": "Server Konfiguration", - "UIText_DiscordIntegration": "Discord Integration", - "UIText_DetectionManager": "Erkennungsmanager", - "UIText_ConfigurationWizard": "Konfigurations-Assistent", - "UIText_PleaseSelectSection": "Bitte wähle oben eine Konfigurationssektion aus", - "UIText_UseWizardAlternative": "Alternativ nutze den Konfigurations-Assistenten zur Serverkonfiguration.", - "UIText_BasicSettings": "Basis", - "UIText_NetworkSettings": "Netzwerk", - "UIText_AdvancedSettings": "Erweitert", - "basic": { - "UIText_BasicServerSettings": "Grundlegende Servereinstellungen", - "UIText_ServerName": "Servername", - "UIText_ServerNameInfo": "Name in der Serverliste angezeigt", - "UIText_SaveFileName": "Speicherdatei Name", - "UIText_SaveFileNameInfo": "Name des Speicherordners. Muss großgeschrieben sein. Für neue Welt, Welttyp angeben. Es wird empfohlen, diesen Wert über den Setup Assistent zu konfigurieren um ihn korrekt zu setzen. ", - "UIText_SaveFileNameUseWizzardButtonText": "Öffne Assistent", - "UIText_MaxPlayers": "Max Spieler", - "UIText_MaxPlayersInfo": "Maximale Anzahl erlaubter Spieler", - "UIText_ServerPassword": "Server Passwort", - "UIText_ServerPasswordInfo": "Leer lassen für kein Passwort", - "UIText_AdminPassword": "Admin Passwort", - "UIText_AdminPasswordInfo": "Server Admin Passwort", - "UIText_AutoSave": "Auto Speichern", - "UIText_AutoSaveInfo": "Auf TRUE setzen für automatisches Speichern", - "UIText_SaveInterval": "Speicher Intervall", - "UIText_SaveIntervalInfo": "Zeit in Sekunden zwischen Speichervorgängen", - "UIText_AutoPauseServer": "Server Auto Pausieren", - "UIText_AutoPauseServerInfo": "Server automatisch pausieren wenn keine Spieler verbunden" - }, - "network": { - "UIText_NetworkConfiguration": "Netzwerk Konfiguration", - "UIText_GamePort": "Spiel Port", - "UIText_GamePortInfo": "Standard: 27016", - "UIText_UpdatePort": "Update Port", - "UIText_UpdatePortInfo": "Standard: 27015", - "UIText_UPNPEnabled": "UPNP Aktiviert", - "UIText_UPNPEnabledInfo": "Automatische UPNP Portweiterleitung aktivieren", - "UIText_LocalIpAddress": "Lokale IP Adresse", - "UIText_LocalIpAddressInfo": "IP Adresse zum Binden", - "UIText_StartLocalHost": "Lokalen Host Starten", - "UIText_StartLocalHostInfo": "Auf TRUE setzen. Dies ist erforderlich für den Server um zu funktionieren.", - "UIText_ServerVisible": "Server Sichtbar", - "UIText_ServerVisibleInfo": "Auf TRUE setzen um Server öffentlich zu listen", - "UIText_UseSteamP2P": "Steam P2P Nutzen", - "UIText_UseSteamP2PInfo": "Steam Peer-to-Peer Netzwerk aktivieren" - }, - "advanced": { - "UIText_AdvancedConfiguration": "Erweiterte Konfiguration", - "UIText_ServerAuthSecret": "Server Auth Geheimnis", - "UIText_ServerAuthSecretInfo": "Authentifizierungsgeheimnis für Server (optional)", - "UIText_ServerExePath": "Server Ausführungspfad", - "UIText_ServerExePathInfo": "Systempfad zur Server-Anwendung", - "UIText_ServerExePathInfo2": "Aus Sicherheitsgründen nicht über UI editierbar, aber manuell in config.json änderbar.", - "UIText_AdditionalParams": "Zusätzliche Parameter", - "UIText_AdditionalParamsInfo": "Format: EigenParam1 Wert1 EigenParam2 Wert2", - "UIText_AutoRestartServerTimer": "Geplanter Gameserver Neustart", - "UIText_AutoRestartServerTimerInfo": "Zeitrahmen in Minuten für automatischen Gameserver Neustart. 0 = deaktiviert, 1440 = 24 Stunden, etc. Mit SSCM siehst du \"Achtung, Server startet neu in 30/20/10/5 Sekunden!\" Nachrichten im Spiel.", - "UIText_GameBranch": "Spiel Branch", - "UIText_GameBranchInfo": "Branch des Spiels. Bei Änderung SSUI Neustart erforderlich!" - }, - "terrain": { - "UIText_Difficulty": "Schwierigkeit", - "UIText_DifficultyInfo": "Schwierigkeit für Welterstellung. Standard Normal wenn leer.", - "UIText_StartCondition": "Startbedingung", - "UIText_StartConditionInfo": "Startbedingung für Welterstellung. Standard-Startbedingung für Welttyp wenn leer.", - "UIText_StartLocation": "Startort", - "UIText_StartLocationInfo": "Startort für Welterstellung. Standard DefaultStartLocation wenn leer.", - "UIText_AutoStartServerOnStartup": "Server Auto-Start beim Hochfahren", - "UIText_AutoStartServerOnStartupInfo": "Gameserver automatisch starten wenn SSUI gestartet wird. Standard false.", - "UIText_AllowAutoGameServerUpdates": "Automatische Spielserver-Updates aktivieren", - "UIText_AllowAutoGameServerUpdatesInfo": "Erlaubt dem Spielserver, automatisch nach der neuesten Version zu suchen und diese zu installieren. Achtung: Der Server wird neu gestartet, wenn eine neue Version gefunden und installiert wurde. 60 bis 10 Sekunden vor dem Neustart werden mehrere Warnmeldungen mit SAY-Befehlen an den Server gesendet." - - }, - "discord": { - "UIText_DiscordIntegrationTitle": "Discord Integration Vorteile", - "UIText_DiscordBotToken": "Discord Bot Token", - "UIText_DiscordBotTokenInfo": "Authentifizierungstoken deines Discord Bots", - "UIText_ChannelConfiguration": "Channel Konfiguration", - "UIText_AdminCommandChannel": "Admin Command Channel", - "UIText_AdminCommandChannelInfo": "Channel für Admin-Befehle", - "UIText_ControlPanelChannel": "Kontrollpanel Channel", - "UIText_ControlPanelChannelInfo": "Channel für Kontrollpanel", - "UIText_StatusChannel": "Status Channel", - "UIText_StatusChannelInfo": "Server Status Updates", - "UIText_ConnectionListChannel": "Verbindungslisten Channel", - "UIText_ConnectionListChannelInfo": "Spielerverbindungs-Tracking", - "UIText_LogChannel": "Log Channel", - "UIText_LogChannelInfo": "Server Log Ausgabe", - "UIText_SaveInfoChannel": "Speicherinfo Channel", - "UIText_SaveInfoChannelInfo": "Speicherdatei Informationen", - "UIText_ErrorChannel": "Fehler Channel", - "UIText_ErrorChannelInfo": "Server Fehlermeldungen", - "UIText_BannedPlayersListPath": "Gesperrte Spieler Liste Pfad", - "UIText_BannedPlayersListPathInfo": "Dateipfad zur gesperrten Spieler Liste", - "UIText_DiscordIntegrationBenefits": "Discord Integration Vorteile", - "UIText_DiscordBenefit1": "Server Status in Echtzeit überwachen", - "UIText_DiscordBenefit2": "Neustarts und Wiederherstellungen remote verwalten", - "UIText_DiscordBenefit3": "Spielerverbindungen verfolgen", - "UIText_DiscordBenefit4": "Community-Management Optionen", - "UIText_DiscordBenefit5": "Echtzeit Fehlerbenachrichtigungen", - "UIText_DiscordSetupInstructions": "Für Setup-Anweisungen besuche die" - } - }, - "setup": { - "UIText_FooterText": "Hilfe benötigt? Schaue ins Stationeers Server UI Github Wiki.", - "UIText_FooterTextInfo": "Du kannst das Setup jederzeit beenden, jeder Schritt wird einzeln gespeichert.", - "UIText_SSCM_FooterText": "Nutze SSCM für das mächtigste Stationeers Server Management! Du kannst Befehle von der Web-Konsole ausführen ohne Vanilla-Verhalten zu stören!", - "UIText_Welcome_Title": "Stationeers Server UI", - "UIText_Welcome_HeaderTitle": "Willkommen!", - "UIText_Welcome_SubmitButton": "Setup Starten", - "UIText_Welcome_SkipButton": "Setup Überspringen", - "UIText_PlsRead_Title": "Bitte lesen!", - "UIText_PlsRead_HeaderTitle": "Hinweis", - "UIText_PlsRead_StepMessage": "Wir empfehlen stark, die Texte in diesem Setup-Assistenten zu lesen! Die meisten gemeldeten Probleme entstehen durch Fehlkonfiguration.", - "UIText_PlsRead_SubmitButton": "Verstanden", - "UIText_PlsRead_SkipButton": "Verstanden", - "UIText_ServerName_Title": "Stationeers Server UI", - "UIText_ServerName_HeaderTitle": "Servername", - "UIText_ServerName_StepMessage": "Gib deinem Server einen Namen wie 'Weltraumstation 13'", - "UIText_ServerName_PrimaryPlaceholder": "Mein Stationeers Server mit UI", - "UIText_ServerName_PrimaryLabel": "Servername", - "UIText_ServerName_SubmitButton": "Speichern & Weiter", - "UIText_ServerName_SkipButton": "Überspringen", - "UIText_SaveIdentifier_Title": "Stationeers Server UI", - "UIText_SaveIdentifier_HeaderTitle": "Speicherstand", - "UIText_SaveIdentifier_StepMessage": "Konfiguriere unten den Namen deines Speicherstands und den Welttyp.", - "UIText_SaveIdentifier_PrimaryLabel": "Name deiner Karte", - "UIText_SaveIdentifier_PrimaryPlaceholder": "MeineStationeersKarte", - "UIText_SaveIdentifier_SecondaryLabel": "Stationeers-Welttyp", - "UIText_SaveIdentifier_SecondaryPlaceholder": "Klicke, um einen Welttyp auszuwählen", - "UIText_SaveIdentifier_SubmitButton": "Speichern & Weiter", - "UIText_SaveIdentifier_SkipButton": "Überspringen", - "UIText_MaxPlayers_Title": "Stationeers Server UI", - "UIText_MaxPlayers_HeaderTitle": "Spielerlimit", - "UIText_MaxPlayers_StepMessage": "Wähle die maximale Anzahl Spieler die sich verbinden können.", - "UIText_MaxPlayers_PrimaryPlaceholder": "8", - "UIText_MaxPlayers_PrimaryLabel": "Max Spieler", - "UIText_MaxPlayers_SubmitButton": "Speichern & Weiter", - "UIText_MaxPlayers_SkipButton": "Überspringen", - "UIText_ServerPassword_Title": "Stationeers Server UI", - "UIText_ServerPassword_HeaderTitle": "Server Passwort", - "UIText_ServerPassword_StepMessage": "Setze ein Gameserver Passwort oder überspringe diesen Schritt.", - "UIText_ServerPassword_PrimaryPlaceholder": "Server Passwort", - "UIText_ServerPassword_PrimaryLabel": "Server Passwort", - "UIText_ServerPassword_SubmitButton": "Speichern & Weiter", - "UIText_ServerPassword_SkipButton": "Überspringen", - "UIText_GameBranch_Title": "Stationeers Server UI", - "UIText_GameBranch_HeaderTitle": "Spiel Branch", - "UIText_GameBranch_StepMessage": "Gib einen Beta-Branch ein oder überspringe für Release-Version. Wenn Sie den Zweig wechseln, klicken Sie nach Abschluss dieses Assistenten unbedingt auf „Server aktualisieren“ im Haupt-Dashboard.", - "UIText_GameBranch_SecondaryPlaceholder": "Wähle einen Zweig", - "UIText_GameBranch_SecondaryLabel": "Spielzweig", - "UIText_GameBranch_SubmitButton": "Speichern & Weiter", - "UIText_GameBranch_SkipButton": "Release Version nutzen", - "UIText_NewTerrainAndSaveSystem_Title": "Wichtig", - "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Terrainsystem wählen", - "UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder": "nein", - "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Neues System aktivieren", - "UIText_NewTerrainAndSaveSystem_SubmitButton": "Speichern & Weiter", - "UIText_NewTerrainAndSaveSystem_SkipButton": "Überspringen", - "UIText_NetworkConfigChoice_Title": "Stationeers Server UI", - "UIText_NetworkConfigChoice_HeaderTitle": "Netzwerk Konfiguration", - "UIText_NetworkConfigChoice_StepMessage": "Netzwerkeinstellungen konfigurieren? 'ja' für Konfiguration oder Überspringen für Standards. Hinweis: Netzwerkkonfiguration besonders wichtig auf Linux Servern.", - "UIText_NetworkConfigChoice_PrimaryPlaceholder": "ja", - "UIText_NetworkConfigChoice_PrimaryLabel": "Netzwerk Konfigurieren", - "UIText_NetworkConfigChoice_SubmitButton": "Weiter", - "UIText_NetworkConfigChoice_SkipButton": "Überspringen (Standards nutzen)", - "UIText_GamePort_Title": "Stationeers Server UI", - "UIText_GamePort_HeaderTitle": "Netzwerk (1/4)", - "UIText_GamePort_StepMessage": "Port-Nummer für Spielverbindungen eingeben", - "UIText_GamePort_PrimaryPlaceholder": "27016", - "UIText_GamePort_PrimaryLabel": "Spiel Port", - "UIText_GamePort_SubmitButton": "Speichern & Weiter", - "UIText_GamePort_SkipButton": "Überspringen", - "UIText_UpdatePort_Title": "Stationeers Server UI", - "UIText_UpdatePort_HeaderTitle": "Netzwerk (2/4)", - "UIText_UpdatePort_StepMessage": "Port-Nummer für Update-Verbindungen eingeben", - "UIText_UpdatePort_PrimaryPlaceholder": "27015", - "UIText_UpdatePort_PrimaryLabel": "Update Port", - "UIText_UpdatePort_SubmitButton": "Speichern & Weiter", - "UIText_UpdatePort_SkipButton": "Überspringen", - "UIText_UPnPEnabled_Title": "Stationeers Server UI", - "UIText_UPnPEnabled_HeaderTitle": "Netzwerk (3/4)", - "UIText_UPnPEnabled_StepMessage": "UPnP aktivieren? 'ja' zum Aktivieren oder 'nein' zum Deaktivieren.", - "UIText_UPnPEnabled_PrimaryPlaceholder": "ja/nein", - "UIText_UPnPEnabled_PrimaryLabel": "UPnP Aktivieren", - "UIText_UPnPEnabled_SubmitButton": "Speichern & Weiter", - "UIText_UPnPEnabled_SkipButton": "Überspringen", - "UIText_LocalIPAddress_Title": "Stationeers Server UI", - "UIText_LocalIPAddress_HeaderTitle": "Netzwerk (4/4)", - "UIText_LocalIPAddress_StepMessage": "Lokale IP-Adresse des Servers im Format 0.0.0.0 eingeben (keine CIDR Notation)", - "UIText_LocalIPAddress_PrimaryPlaceholder": "0.0.0.0", - "UIText_LocalIPAddress_PrimaryLabel": "Lokale IP-Adresse", - "UIText_LocalIPAddress_SubmitButton": "Speichern & Weiter", - "UIText_LocalIPAddress_SkipButton": "Überspringen", - "UIText_AdminAccount_Title": "Stationeers Server UI", - "UIText_AdminAccount_HeaderTitle": "Adminkonto", - "UIText_AdminAccount_StepMessage": "Richte dein Adminkonto ein.", - "UIText_AdminAccount_PrimaryPlaceholder": "Benutzername", - "UIText_AdminAccount_PrimaryLabel": "Benutzername", - "UIText_AdminAccount_SecondaryLabel": "Passwort", - "UIText_AdminAccount_SecondaryPlaceholder": "Passwort", - "UIText_AdminAccount_SubmitButton": "Speichern & Weiter", - "UIText_AdminAccount_SkipButton": "Authentifizierung Überspringen", - "UIText_Finalize_Title": "Das wars!", - "UIText_Finalize_HeaderTitle": "Setup Abschließen", - "UIText_Finalize_StepMessage": "Bereit zum Abschließen? Deine Konfiguration wurde bereits während des Setups gespeichert. Für Änderungen klicke 'Zurück zum Start' und überspringe was behalten werden soll. Meiste Optionen auch im Config Tab änderbar.", - "UIText_Finalize_SubmitButton": "Zurück zum Start", - "UIText_Finalize_SkipButton": "Authentifizierung Überspringen", - "UIText_Login_Title": "Stationeers Server UI", - "UIText_Login_HeaderTitle": "Login", - "UIText_Login_PrimaryLabel": "Benutzername", - "UIText_Login_SecondaryLabel": "Passwort", - "UIText_Login_PrimaryPlaceholder": "Benutzername eingeben", - "UIText_Login_SecondaryPlaceholder": "Passwort eingeben", - "UIText_Login_SubmitButton": "Anmelden", - "UIText_ChangeUser_Title": "Stationeers Server UI", - "UIText_ChangeUser_HeaderTitle": "Benutzer Verwalten", - "UIText_ChangeUser_PrimaryLabel": "Benutzername Hinzufügen/Aktualisieren", - "UIText_ChangeUser_SecondaryLabel": "Neues Passwort", - "UIText_ChangeUser_SecondaryPlaceholder": "Passwort", - "UIText_ChangeUser_SubmitButton": "Benutzer Hinzufügen/Aktualisieren" - } - }, - "BackendText": { - "gamemgr": { - "BackendText_ServerStarted": "Server gestartet.", - "BackendText_ServerNotRunningOrAlreadyStopped": "Server war nicht gestartet oder wurde bereits gestoppt", - "BackendText_ServerStopped": "Server gestoppt." + "BackendText": { + "gamemgr": { + "BackendText_ServerStarted": "Server gestartet.", + "BackendText_ServerNotRunningOrAlreadyStopped": "Server war nicht gestartet oder wurde bereits gestoppt", + "BackendText_ServerStopped": "Server gestoppt." + } } - } -} \ No newline at end of file +} diff --git a/UIMod/onboard_bundled/localization/en-US.json b/UIMod/onboard_bundled/localization/en-US.json index b41e566c..1deb7f4a 100644 --- a/UIMod/onboard_bundled/localization/en-US.json +++ b/UIMod/onboard_bundled/localization/en-US.json @@ -1,259 +1,255 @@ { - "UIText": { - "index": { - "UIText_StartButton": "Start Server", - "UIText_StopButton": "Stop Server", - "UIText_Settings": "Edit Config", - "UIText_Update_SteamCMD": "Update Server", - "UIText_Console": "Game Log", - "UIText_Detection_Events": "Events", - "UIText_Backend_Log": "Backend Log", - "UIText_Backup_Manager": "Backup Manager", - "UIText_Connected_PlayersHeader": "Connected Players", - "UIText_Discord_Info": "Join the Discord and help make SSUI better or get support!", - "UIText_API_Info": "API Endpoint Reference", - "UIText_Copyright": "Copyright", - "UIText_Copyright1": "Licensed under", - "UIText_Copyright2": "Proprietary License" + "UIText": { + "index": { + "UIText_StartButton": "Start Server", + "UIText_StopButton": "Stop Server", + "UIText_Settings": "Edit Config", + "UIText_Update_SteamCMD": "Update Server", + "UIText_Console": "Game Log", + "UIText_Detection_Events": "Events", + "UIText_Backend_Log": "Backend Log", + "UIText_Backup_Manager": "Backup Manager", + "UIText_Connected_PlayersHeader": "Connected Players", + "UIText_Discord_Info": "Join the Discord and help make SSUI better or get support!", + "UIText_API_Info": "API Endpoint Reference", + "UIText_Copyright": "Copyright", + "UIText_Copyright1": "Licensed under", + "UIText_Copyright2": "Proprietary License" + }, + "config": { + "UIText_ServerConfig": "Server Configuration", + "UIText_DiscordIntegration": "Discord Integration", + "UIText_DetectionManager": "Detection Manager", + "UIText_ConfigurationWizard": "Configuration Wizard", + "UIText_PleaseSelectSection": "Please select a configuration section above", + "UIText_UseWizardAlternative": "Alternatively, use the Configuration Wizard to configure the server.", + "UIText_BasicSettings": "Basic Settings", + "UIText_NetworkSettings": "Network Settings", + "UIText_AdvancedSettings": "Advanced Settings", + "UIText_TerrainSettings": "New Terrain", + "basic": { + "UIText_BasicServerSettings": "Basic Server Settings", + "UIText_ServerName": "Server Name", + "UIText_ServerNameInfo": "Name displayed in server list", + "UIText_SaveFileName": "Save File Name", + "UIText_SaveFileNameInfo": "Name of save folder. Must be capitalized. To create a new world, provide the World type to generate. It is recommended to use the Wizard to configure this value correctly. ", + "UIText_SaveFileNameUseWizzardButtonText": "Open Wizard", + "UIText_MaxPlayers": "Max Players", + "UIText_MaxPlayersInfo": "Maximum number of players allowed", + "UIText_ServerPassword": "Server Password", + "UIText_ServerPasswordInfo": "Leave empty for no password", + "UIText_AdminPassword": "Admin Password", + "UIText_AdminPasswordInfo": "Server Admin Password", + "UIText_AutoSave": "Auto Save", + "UIText_AutoSaveInfo": "Set to TRUE to enable automatic saving", + "UIText_SaveInterval": "Save Interval", + "UIText_SaveIntervalInfo": "Time in seconds between saves. Recommended to not recede 60 seconds.", + "UIText_AutoPauseServer": "Auto Pause Server", + "UIText_AutoPauseServerInfo": "Automatically pause server when no players are connected" + }, + "network": { + "UIText_NetworkConfiguration": "Network Configuration", + "UIText_GamePort": "Game Port", + "UIText_GamePortInfo": "Default: 27016", + "UIText_UpdatePort": "Update Port", + "UIText_UpdatePortInfo": "Default: 27015", + "UIText_UPNPEnabled": "UPNP Enabled", + "UIText_UPNPEnabledInfo": "Enable automatic UPNP port forwarding", + "UIText_LocalIpAddress": "Local IP Address", + "UIText_LocalIpAddressInfo": "IP address to bind to", + "UIText_StartLocalHost": "Start Local Host", + "UIText_StartLocalHostInfo": "Keep this true. This is required for the server to work.", + "UIText_ServerVisible": "Server Visible", + "UIText_ServerVisibleInfo": "Set to TRUE to list server publicly", + "UIText_UseSteamP2P": "Use Steam P2P", + "UIText_UseSteamP2PInfo": "Enable Steam Peer-to-Peer networking" + }, + "advanced": { + "UIText_AdvancedConfiguration": "Advanced Configuration", + "UIText_ServerAuthSecret": "Server Auth Secret", + "UIText_ServerAuthSecretInfo": "Authentication secret for the server (optional)", + "UIText_ServerExePath": "Server Executable Path", + "UIText_ServerExePathInfo": "System path to server executable", + "UIText_ServerExePathInfo2": "Not editable from the UI for security reasons, but you can edit it manually in the config.json file.", + "UIText_AdditionalParams": "Additional Parameters", + "UIText_AdditionalParamsInfo": "Format: CustomParam1 Value1 CustomParam2 Value2", + "UIText_AutoRestartServerTimer": "Scheduled Gameserver Restart", + "UIText_AutoRestartServerTimerInfo": "

Timeframe in minutes or time format (e.g., 15:04 or 03:04PM) to schedule an automatic gameserver restart. 0 = disabled, 1440 = 24 hours, etc. You will see 'Attention, server is restarting in 30/20/10/5 seconds!' messages ingame before the restart.

", + "UIText_GameBranch": "Game Branch", + "UIText_GameBranchInfo": "Branch of the game to use. When changed, requires to restart SSUI!", + "UIText_AllowAutoGameServerUpdates": "Enable Auto Game Server Updates", + "UIText_AllowAutoGameServerUpdatesInfo": "Allow the gameserver to automatically query for and update to the latest version. Attention: Restarts the server when a new version was found and installed. Will send multiple warning messages to the sever with SAY commands 60-10 seconds before the restart." + }, + "terrain": { + "UIText_TerrainSettingsHeader": "NEW TERRAIN AND SAVE SYSTEM SETTINGS", + "UIText_TerrainWarning": "These settings are only useful if you are running a Stationeers build NEWER than September 2025. Old savegames are NOT compatible with the new system, but can be migrated with JacksonTheMaster's Migration tool.. Related \"how to\" Information on the FAQ there also applies to the Dedicated Server.", + "UIText_UseNewTerrainAndSave": "Use New Terrain and Save System", + "UIText_UseNewTerrainAndSaveInfo": "Set to TRUE to enable handling of .save files in the Backup manager and argument parsing. If set to false, only Stationeers versions before the terrain rework (≈ mid 2025) will work. Defaults to TRUE!", + "UIText_Difficulty": "Difficulty", + "UIText_DifficultyInfo": "Difficulty to create the world with. Defaults to Normal if empty.", + "UIText_StartCondition": "Start Condition", + "UIText_StartConditionInfo": "Start condition to create the world with. Defaults to the default start condition for the world type if empty.", + "UIText_StartLocation": "Start Location", + "UIText_StartLocationInfo": "Start location to create the world with. Defaults to DefaultStartLocation if empty.", + "UIText_AutoStartServerOnStartup": "Auto Start Server on Startup", + "UIText_AutoStartServerOnStartupInfo": "Automatically start the gameserver when the SSUI is started. Defaults to false." + }, + "discord": { + "UIText_DiscordIntegrationTitle": "Discord Integration Benefits", + "UIText_DiscordBotToken": "Discord Bot Token", + "UIText_DiscordBotTokenInfo": "Your Discord bot's authentication token", + "UIText_ChannelConfiguration": "Channel Configuration", + "UIText_AdminCommandChannel": "Admin Command Channel", + "UIText_AdminCommandChannelInfo": "Channel for admin commands", + "UIText_ControlPanelChannel": "Control Panel Channel", + "UIText_ControlPanelChannelInfo": "Channel for control panel", + "UIText_StatusChannel": "Status Channel", + "UIText_StatusChannelInfo": "Server status updates", + "UIText_ConnectionListChannel": "Connection List Channel", + "UIText_ConnectionListChannelInfo": "Player connection tracking", + "UIText_LogChannel": "Log Channel", + "UIText_LogChannelInfo": "Server log output", + "UIText_SaveInfoChannel": "Save Info Channel", + "UIText_SaveInfoChannelInfo": "Save file information", + "UIText_ErrorChannel": "Error Channel", + "UIText_ErrorChannelInfo": "Server error messages", + "UIText_BannedPlayersListPath": "Banned Players List Path", + "UIText_BannedPlayersListPathInfo": "File path to banned players list", + "UIText_DiscordIntegrationBenefits": "Discord Integration Benefits", + "UIText_DiscordBenefit1": "Monitor server status in real-time", + "UIText_DiscordBenefit2": "Manage restarts and restores remotely", + "UIText_DiscordBenefit3": "Track player connections", + "UIText_DiscordBenefit4": "Community management options", + "UIText_DiscordBenefit5": "Real-time error notifications", + "UIText_DiscordSetupInstructions": "For setup instructions, visit the" + } + }, + "setup": { + "UIText_FooterText": "Need help? Check the Stationeers Server UI Github Wiki.", + "UIText_FooterTextInfo": "You may exit the wizard at any time, each step is saved individually.", + "UIText_SSCM_FooterText": "Use SSCM for the most powerful Stationeers server management! You can run commands from the Web console without disrupting vanilla behaviour!", + "UIText_Welcome_Title": "Stationeers Server UI", + "UIText_Welcome_HeaderTitle": "Welcome!", + "UIText_Welcome_SubmitButton": "Start Setup", + "UIText_Welcome_SkipButton": "Skip Setup", + "UIText_PlsRead_Title": "Please read!", + "UIText_PlsRead_HeaderTitle": "Disclaimer", + "UIText_PlsRead_StepMessage": "We strongly recommend you to read the texts in this setup wizard! Most reported issues occur because of a misconfiguration.", + "UIText_PlsRead_SubmitButton": "I understand", + "UIText_PlsRead_SkipButton": "I understand", + "UIText_ServerName_Title": "Stationeers Server UI", + "UIText_ServerName_HeaderTitle": "Server Name", + "UIText_ServerName_StepMessage": "Give your server a name like 'Space Station 13'", + "UIText_ServerName_PrimaryPlaceholder": "My Stationeers Server with UI", + "UIText_ServerName_PrimaryLabel": "Server Name", + "UIText_ServerName_SubmitButton": "Save & Continue", + "UIText_ServerName_SkipButton": "Skip", + "UIText_SaveIdentifier_Title": "Stationeers Server UI", + "UIText_SaveIdentifier_HeaderTitle": "Save Identifier", + "UIText_SaveIdentifier_StepMessage": "Configue your savegame name and world type from the options below.", + "UIText_SaveIdentifier_PrimaryLabel": "Your Map Name", + "UIText_SaveIdentifier_PrimaryPlaceholder": "MyStationeersMap", + "UIText_SaveIdentifier_SecondaryLabel": "Stationeers World Type", + "UIText_SaveIdentifier_SecondaryPlaceholder": "Click to select a world type", + "UIText_SaveIdentifier_SubmitButton": "Save & Continue", + "UIText_SaveIdentifier_SkipButton": "Skip", + "UIText_MaxPlayers_Title": "Stationeers Server UI", + "UIText_MaxPlayers_HeaderTitle": "Player Limit", + "UIText_MaxPlayers_StepMessage": "Choose the maximum number of players that can connect to the server. Recommended to not exceed 20", + "UIText_MaxPlayers_PrimaryPlaceholder": "8", + "UIText_MaxPlayers_PrimaryLabel": "Max Players", + "UIText_MaxPlayers_SubmitButton": "Save & Continue", + "UIText_MaxPlayers_SkipButton": "Skip", + "UIText_ServerPassword_Title": "Stationeers Server UI", + "UIText_ServerPassword_HeaderTitle": "Server Password", + "UIText_ServerPassword_StepMessage": "Set a gameserver password or skip this step.", + "UIText_ServerPassword_PrimaryPlaceholder": "Server Password", + "UIText_ServerPassword_PrimaryLabel": "Server Password", + "UIText_ServerPassword_SubmitButton": "Save & Continue", + "UIText_ServerPassword_SkipButton": "Skip", + "UIText_GameBranch_Title": "Stationeers Server UI", + "UIText_GameBranch_HeaderTitle": "Game Branch", + "UIText_GameBranch_StepMessage": "Enter a beta branch or skip this to use the release version. If switching branches, make sure to click Update Server on the Main dashboard after completing this wizzard.", + "UIText_GameBranch_SecondaryPlaceholder": "Select a branch", + "UIText_GameBranch_SecondaryLabel": "Game Branch", + "UIText_GameBranch_SubmitButton": "Save & Continue", + "UIText_GameBranch_SkipButton": "Use Normal Version", + "UIText_NewTerrainAndSaveSystem_Title": "IMPORTANT", + "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Select Terrain System", + "UIText_NewTerrainAndSaveSystem_StepMessage": "Using an OLD branch, such as preterrain or older without the terrain system changes? If yes, disable handling of the new terrain and save system here. Enter 'yes' or skip to enable (default) or 'no' to use the old save and terrain system. If you are unsure, skip this step.", + "UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder": "yes", + "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Enable new System", + "UIText_NewTerrainAndSaveSystem_SubmitButton": "Save & Continue", + "UIText_NewTerrainAndSaveSystem_SkipButton": "Skip", + "UIText_NetworkConfigChoice_Title": "Stationeers Server UI", + "UIText_NetworkConfigChoice_HeaderTitle": "Network Configuration", + "UIText_NetworkConfigChoice_StepMessage": "Do you want to configure network settings? Enter 'yes' to configure or Skip to use defaults. Note: Network configuration is especially important on Linux servers.", + "UIText_NetworkConfigChoice_PrimaryPlaceholder": "yes", + "UIText_NetworkConfigChoice_PrimaryLabel": "Configure Network", + "UIText_NetworkConfigChoice_SubmitButton": "Continue", + "UIText_NetworkConfigChoice_SkipButton": "Skip (Use Defaults)", + "UIText_GamePort_Title": "Stationeers Server UI", + "UIText_GamePort_HeaderTitle": "Network (1/4)", + "UIText_GamePort_StepMessage": "Enter the port number for game connections", + "UIText_GamePort_PrimaryPlaceholder": "27016", + "UIText_GamePort_PrimaryLabel": "Game Port", + "UIText_GamePort_SubmitButton": "Save & Continue", + "UIText_GamePort_SkipButton": "Skip", + "UIText_UpdatePort_Title": "Stationeers Server UI", + "UIText_UpdatePort_HeaderTitle": "Network (2/4)", + "UIText_UpdatePort_StepMessage": "Enter the port number for update connections", + "UIText_UpdatePort_PrimaryPlaceholder": "27015", + "UIText_UpdatePort_PrimaryLabel": "Update Port", + "UIText_UpdatePort_SubmitButton": "Save & Continue", + "UIText_UpdatePort_SkipButton": "Skip", + "UIText_UPnPEnabled_Title": "Stationeers Server UI", + "UIText_UPnPEnabled_HeaderTitle": "Network (3/4)", + "UIText_UPnPEnabled_StepMessage": "Enable UPnP? Enter 'yes' to enable or 'no' to disable.", + "UIText_UPnPEnabled_PrimaryPlaceholder": "yes/no", + "UIText_UPnPEnabled_PrimaryLabel": "Enable UPnP", + "UIText_UPnPEnabled_SubmitButton": "Save & Continue", + "UIText_UPnPEnabled_SkipButton": "Skip", + "UIText_LocalIPAddress_Title": "Stationeers Server UI", + "UIText_LocalIPAddress_HeaderTitle": "Network (4/4)", + "UIText_LocalIPAddress_StepMessage": "Enter server's local IP address in format 0.0.0.0 (no CIDR notation)", + "UIText_LocalIPAddress_PrimaryPlaceholder": "0.0.0.0", + "UIText_LocalIPAddress_PrimaryLabel": "Local IP Address", + "UIText_LocalIPAddress_SubmitButton": "Save & Continue", + "UIText_LocalIPAddress_SkipButton": "Skip", + "UIText_AdminAccount_Title": "Stationeers Server UI", + "UIText_AdminAccount_HeaderTitle": "Admin Account", + "UIText_AdminAccount_StepMessage": "Set up your SSUI admin account.", + "UIText_AdminAccount_PrimaryPlaceholder": "Username", + "UIText_AdminAccount_PrimaryLabel": "Username", + "UIText_AdminAccount_SecondaryLabel": "Password", + "UIText_AdminAccount_SecondaryPlaceholder": "Password", + "UIText_AdminAccount_SubmitButton": "Save & Continue", + "UIText_AdminAccount_SkipButton": "Skip Authentication", + "UIText_Finalize_Title": "You did it", + "UIText_Finalize_HeaderTitle": "Finalize Setup", + "UIText_Finalize_StepMessage": "Ready to finalize? Your configuration has already been saved while you completed this setup. If you want to change any of the settings, you may click Return to Start and skip whatever you want to keep. Most options can also be changed on the config Tab in the UI later.", + "UIText_Finalize_SubmitButton": "Return to Start", + "UIText_Finalize_SkipButton": "Skip Authentication", + "UIText_Login_Title": "Stationeers Server UI", + "UIText_Login_HeaderTitle": "Login", + "UIText_Login_PrimaryLabel": "Username", + "UIText_Login_SecondaryLabel": "Password", + "UIText_Login_PrimaryPlaceholder": "Enter Username", + "UIText_Login_SecondaryPlaceholder": "Enter Password", + "UIText_Login_SubmitButton": "Login", + "UIText_ChangeUser_Title": "Stationeers Server UI", + "UIText_ChangeUser_HeaderTitle": "Manage Users", + "UIText_ChangeUser_PrimaryLabel": "Username to Add/Update", + "UIText_ChangeUser_SecondaryLabel": "New Password", + "UIText_ChangeUser_SecondaryPlaceholder": "Password", + "UIText_ChangeUser_SubmitButton": "Add/Update User" + } }, - "config": { - "UIText_ServerConfig": "Server Configuration", - "UIText_DiscordIntegration": "Discord Integration", - "UIText_DetectionManager": "Detection Manager", - "UIText_ConfigurationWizard": "Configuration Wizard", - "UIText_PleaseSelectSection": "Please select a configuration section above", - "UIText_UseWizardAlternative": "Alternatively, use the Configuration Wizard to configure the server.", - "UIText_BasicSettings": "Basic Settings", - "UIText_NetworkSettings": "Network Settings", - "UIText_AdvancedSettings": "Advanced Settings", - "UIText_TerrainSettings": "New Terrain", - "basic": { - "UIText_BasicServerSettings": "Basic Server Settings", - "UIText_ServerName": "Server Name", - "UIText_ServerNameInfo": "Name displayed in server list", - "UIText_SaveFileName": "Save File Name", - "UIText_SaveFileNameInfo": "Name of save folder. Must be capitalized. To create a new world, provide the World type to generate. It is recommended to use the Wizard to configure this value correctly. ", - "UIText_SaveFileNameUseWizzardButtonText": "Open Wizard", - "UIText_MaxPlayers": "Max Players", - "UIText_MaxPlayersInfo": "Maximum number of players allowed", - "UIText_ServerPassword": "Server Password", - "UIText_ServerPasswordInfo": "Leave empty for no password", - "UIText_AdminPassword": "Admin Password", - "UIText_AdminPasswordInfo": "Server Admin Password", - "UIText_AutoSave": "Auto Save", - "UIText_AutoSaveInfo": "Set to TRUE to enable automatic saving", - "UIText_SaveInterval": "Save Interval", - "UIText_SaveIntervalInfo": "Time in seconds between saves. Recommended to not recede 60 seconds.", - "UIText_AutoPauseServer": "Auto Pause Server", - "UIText_AutoPauseServerInfo": "Automatically pause server when no players are connected" - }, - "network": { - "UIText_NetworkConfiguration": "Network Configuration", - "UIText_GamePort": "Game Port", - "UIText_GamePortInfo": "Default: 27016", - "UIText_UpdatePort": "Update Port", - "UIText_UpdatePortInfo": "Default: 27015", - "UIText_UPNPEnabled": "UPNP Enabled", - "UIText_UPNPEnabledInfo": "Enable automatic UPNP port forwarding", - "UIText_LocalIpAddress": "Local IP Address", - "UIText_LocalIpAddressInfo": "IP address to bind to", - "UIText_StartLocalHost": "Start Local Host", - "UIText_StartLocalHostInfo": "Keep this true. This is required for the server to work.", - "UIText_ServerVisible": "Server Visible", - "UIText_ServerVisibleInfo": "Set to TRUE to list server publicly", - "UIText_UseSteamP2P": "Use Steam P2P", - "UIText_UseSteamP2PInfo": "Enable Steam Peer-to-Peer networking" - }, - "advanced": { - "UIText_AdvancedConfiguration": "Advanced Configuration", - "UIText_ServerAuthSecret": "Server Auth Secret", - "UIText_ServerAuthSecretInfo": "Authentication secret for the server (optional)", - "UIText_ServerExePath": "Server Executable Path", - "UIText_ServerExePathInfo": "System path to server executable", - "UIText_ServerExePathInfo2": "Not editable from the UI for security reasons, but you can edit it manually in the config.json file.", - "UIText_AdditionalParams": "Additional Parameters", - "UIText_AdditionalParamsInfo": "Format: CustomParam1 Value1 CustomParam2 Value2", - "UIText_AutoRestartServerTimer": "Scheduled Gameserver Restart", - "UIText_AutoRestartServerTimerInfo": "

Timeframe in minutes or time format (e.g., 15:04 or 03:04PM) to schedule an automatic gameserver restart. 0 = disabled, 1440 = 24 hours, etc. You will see 'Attention, server is restarting in 30/20/10/5 seconds!' messages ingame before the restart.

", - "UIText_GameBranch": "Game Branch", - "UIText_GameBranchInfo": "Branch of the game to use. When changed, requires to restart SSUI!", - "UIText_AllowAutoGameServerUpdates": "Enable Auto Game Server Updates", - "UIText_AllowAutoGameServerUpdatesInfo": "Allow the gameserver to automatically query for and update to the latest version. Attention: Restarts the server when a new version was found and installed. Will send multiple warning messages to the sever with SAY commands 60-10 seconds before the restart." - }, - "terrain": { - "UIText_TerrainSettingsHeader": "NEW TERRAIN AND SAVE SYSTEM SETTINGS", - "UIText_TerrainWarning": "These settings are only useful if you are running a Stationeers build NEWER than September 2025. Old savegames are NOT compatible with the new system, but can be migrated with JacksonTheMaster's Migration tool.. Related \"how to\" Information on the FAQ there also applies to the Dedicated Server.", - "UIText_UseNewTerrainAndSave": "Use New Terrain and Save System", - "UIText_UseNewTerrainAndSaveInfo": "Set to TRUE to enable handling of .save files in the Backup manager and argument parsing. If set to false, only Stationeers versions before the terrain rework (≈ mid 2025) will work. Defaults to TRUE!", - "UIText_Difficulty": "Difficulty", - "UIText_DifficultyInfo": "Difficulty to create the world with. Defaults to Normal if empty.", - "UIText_StartCondition": "Start Condition", - "UIText_StartConditionInfo": "Start condition to create the world with. Defaults to the default start condition for the world type if empty.", - "UIText_StartLocation": "Start Location", - "UIText_StartLocationInfo": "Start location to create the world with. Defaults to DefaultStartLocation if empty.", - "UIText_AutoStartServerOnStartup": "Auto Start Server on Startup", - "UIText_AutoStartServerOnStartupInfo": "Automatically start the gameserver when the SSUI is started. Defaults to false." - }, - "discord": { - "UIText_DiscordIntegrationTitle": "Discord Integration Benefits", - "UIText_DiscordBotToken": "Discord Bot Token", - "UIText_DiscordBotTokenInfo": "Your Discord bot's authentication token", - "UIText_ChannelConfiguration": "Channel Configuration", - "UIText_AdminCommandChannel": "Admin Command Channel", - "UIText_AdminCommandChannelInfo": "Channel for admin commands", - "UIText_ControlPanelChannel": "Control Panel Channel", - "UIText_ControlPanelChannelInfo": "Channel for control panel", - "UIText_StatusChannel": "Status Channel", - "UIText_StatusChannelInfo": "Server status updates", - "UIText_ConnectionListChannel": "Connection List Channel", - "UIText_ConnectionListChannelInfo": "Player connection tracking", - "UIText_LogChannel": "Log Channel", - "UIText_LogChannelInfo": "Server log output", - "UIText_SaveInfoChannel": "Save Info Channel", - "UIText_SaveInfoChannelInfo": "Save file information", - "UIText_ErrorChannel": "Error Channel", - "UIText_ErrorChannelInfo": "Server error messages", - "UIText_BannedPlayersListPath": "Banned Players List Path", - "UIText_BannedPlayersListPathInfo": "File path to banned players list", - "UIText_DiscordIntegrationBenefits": "Discord Integration Benefits", - "UIText_DiscordBenefit1": "Monitor server status in real-time", - "UIText_DiscordBenefit2": "Manage restarts and restores remotely", - "UIText_DiscordBenefit3": "Track player connections", - "UIText_DiscordBenefit4": "Community management options", - "UIText_DiscordBenefit5": "Real-time error notifications", - "UIText_DiscordSetupInstructions": "For setup instructions, visit the" - } - }, - "setup": { - "UIText_FooterText": "Need help? Check the Stationeers Server UI Github Wiki.", - "UIText_FooterTextInfo": "You may exit the wizard at any time, each step is saved individually.", - "UIText_SSCM_FooterText": "Use SSCM for the most powerful Stationeers server management! You can run commands from the Web console without disrupting vanilla behaviour!", - "UIText_Welcome_Title": "Stationeers Server UI", - "UIText_Welcome_HeaderTitle": "Welcome!", - "UIText_Welcome_SubmitButton": "Start Setup", - "UIText_Welcome_SkipButton": "Skip Setup", - "UIText_PlsRead_Title": "Please read!", - "UIText_PlsRead_HeaderTitle": "Disclaimer", - "UIText_PlsRead_StepMessage": "We strongly recommend you to read the texts in this setup wizard! Most reported issues occur because of a misconfiguration.", - "UIText_PlsRead_SubmitButton": "I understand", - "UIText_PlsRead_SkipButton": "I understand", - "UIText_ServerName_Title": "Stationeers Server UI", - "UIText_ServerName_HeaderTitle": "Server Name", - "UIText_ServerName_StepMessage": "Give your server a name like 'Space Station 13'", - "UIText_ServerName_PrimaryPlaceholder": "My Stationeers Server with UI", - "UIText_ServerName_PrimaryLabel": "Server Name", - "UIText_ServerName_SubmitButton": "Save & Continue", - "UIText_ServerName_SkipButton": "Skip", - "UIText_SaveIdentifier_Title": "Stationeers Server UI", - "UIText_SaveIdentifier_HeaderTitle": "Save Identifier", - "UIText_SaveIdentifier_StepMessage": "Configue your savegame name and world type from the options below.", - "UIText_SaveIdentifier_PrimaryLabel": "Your Map Name", - "UIText_SaveIdentifier_PrimaryPlaceholder": "MyStationeersMap", - "UIText_SaveIdentifier_SecondaryLabel": "Stationeers World Type", - "UIText_SaveIdentifier_SecondaryPlaceholder": "Click to select a world type", - "UIText_SaveIdentifier_SubmitButton": "Save & Continue", - "UIText_SaveIdentifier_SkipButton": "Skip", - "UIText_MaxPlayers_Title": "Stationeers Server UI", - "UIText_MaxPlayers_HeaderTitle": "Player Limit", - "UIText_MaxPlayers_StepMessage": "Choose the maximum number of players that can connect to the server. Recommended to not exceed 20", - "UIText_MaxPlayers_PrimaryPlaceholder": "8", - "UIText_MaxPlayers_PrimaryLabel": "Max Players", - "UIText_MaxPlayers_SubmitButton": "Save & Continue", - "UIText_MaxPlayers_SkipButton": "Skip", - "UIText_ServerPassword_Title": "Stationeers Server UI", - "UIText_ServerPassword_HeaderTitle": "Server Password", - "UIText_ServerPassword_StepMessage": "Set a gameserver password or skip this step.", - "UIText_ServerPassword_PrimaryPlaceholder": "Server Password", - "UIText_ServerPassword_PrimaryLabel": "Server Password", - "UIText_ServerPassword_SubmitButton": "Save & Continue", - "UIText_ServerPassword_SkipButton": "Skip", - "UIText_GameBranch_Title": "Stationeers Server UI", - "UIText_GameBranch_HeaderTitle": "Game Branch", - "UIText_GameBranch_StepMessage": "Enter a beta branch or skip this to use the release version. If switching branches, make sure to click Update Server on the Main dashboard after completing this wizzard.", - "UIText_GameBranch_SecondaryPlaceholder": "Select a branch", - "UIText_GameBranch_SecondaryLabel": "Game Branch", - "UIText_GameBranch_SubmitButton": "Save & Continue", - "UIText_GameBranch_SkipButton": "Use Normal Version", - "UIText_NewTerrainAndSaveSystem_Title": "IMPORTANT", - "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Select Terrain System", - "UIText_NewTerrainAndSaveSystem_StepMessage": "Using an OLD branch, such as preterrain or older without the terrain system changes? If yes, disable handling of the new terrain and save system here. Enter 'yes' or skip to enable (default) or 'no' to use the old save and terrain system. If you are unsure, skip this step.", - "UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder": "yes", - "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Enable new System", - "UIText_NewTerrainAndSaveSystem_SubmitButton": "Save & Continue", - "UIText_NewTerrainAndSaveSystem_SkipButton": "Skip", - "UIText_NetworkConfigChoice_Title": "Stationeers Server UI", - "UIText_NetworkConfigChoice_HeaderTitle": "Network Configuration", - "UIText_NetworkConfigChoice_StepMessage": "Do you want to configure network settings? Enter 'yes' to configure or Skip to use defaults. Note: Network configuration is especially important on Linux servers.", - "UIText_NetworkConfigChoice_PrimaryPlaceholder": "yes", - "UIText_NetworkConfigChoice_PrimaryLabel": "Configure Network", - "UIText_NetworkConfigChoice_SubmitButton": "Continue", - "UIText_NetworkConfigChoice_SkipButton": "Skip (Use Defaults)", - "UIText_GamePort_Title": "Stationeers Server UI", - "UIText_GamePort_HeaderTitle": "Network (1/4)", - "UIText_GamePort_StepMessage": "Enter the port number for game connections", - "UIText_GamePort_PrimaryPlaceholder": "27016", - "UIText_GamePort_PrimaryLabel": "Game Port", - "UIText_GamePort_SubmitButton": "Save & Continue", - "UIText_GamePort_SkipButton": "Skip", - "UIText_UpdatePort_Title": "Stationeers Server UI", - "UIText_UpdatePort_HeaderTitle": "Network (2/4)", - "UIText_UpdatePort_StepMessage": "Enter the port number for update connections", - "UIText_UpdatePort_PrimaryPlaceholder": "27015", - "UIText_UpdatePort_PrimaryLabel": "Update Port", - "UIText_UpdatePort_SubmitButton": "Save & Continue", - "UIText_UpdatePort_SkipButton": "Skip", - "UIText_UPnPEnabled_Title": "Stationeers Server UI", - "UIText_UPnPEnabled_HeaderTitle": "Network (3/4)", - "UIText_UPnPEnabled_StepMessage": "Enable UPnP? Enter 'yes' to enable or 'no' to disable.", - "UIText_UPnPEnabled_PrimaryPlaceholder": "yes/no", - "UIText_UPnPEnabled_PrimaryLabel": "Enable UPnP", - "UIText_UPnPEnabled_SubmitButton": "Save & Continue", - "UIText_UPnPEnabled_SkipButton": "Skip", - "UIText_LocalIPAddress_Title": "Stationeers Server UI", - "UIText_LocalIPAddress_HeaderTitle": "Network (4/4)", - "UIText_LocalIPAddress_StepMessage": "Enter server's local IP address in format 0.0.0.0 (no CIDR notation)", - "UIText_LocalIPAddress_PrimaryPlaceholder": "0.0.0.0", - "UIText_LocalIPAddress_PrimaryLabel": "Local IP Address", - "UIText_LocalIPAddress_SubmitButton": "Save & Continue", - "UIText_LocalIPAddress_SkipButton": "Skip", - "UIText_AdminAccount_Title": "Stationeers Server UI", - "UIText_AdminAccount_HeaderTitle": "Admin Account", - "UIText_AdminAccount_StepMessage": "Set up your SSUI admin account.", - "UIText_AdminAccount_PrimaryPlaceholder": "Username", - "UIText_AdminAccount_PrimaryLabel": "Username", - "UIText_AdminAccount_SecondaryLabel": "Password", - "UIText_AdminAccount_SecondaryPlaceholder": "Password", - "UIText_AdminAccount_SubmitButton": "Save & Continue", - "UIText_AdminAccount_SkipButton": "Skip Authentication", - "UIText_Finalize_Title": "You did it", - "UIText_Finalize_HeaderTitle": "Finalize Setup", - "UIText_Finalize_StepMessage": "Ready to finalize? Your configuration has already been saved while you completed this setup. If you want to change any of the settings, you may click Return to Start and skip whatever you want to keep. Most options can also be changed on the config Tab in the UI later.", - "UIText_Finalize_SubmitButton": "Return to Start", - "UIText_Finalize_SkipButton": "Skip Authentication", - "UIText_Login_Title": "Stationeers Server UI", - "UIText_Login_HeaderTitle": "Login", - "UIText_Login_PrimaryLabel": "Username", - "UIText_Login_SecondaryLabel": "Password", - "UIText_Login_PrimaryPlaceholder": "Enter Username", - "UIText_Login_SecondaryPlaceholder": "Enter Password", - "UIText_Login_SubmitButton": "Login", - "UIText_ChangeUser_Title": "Stationeers Server UI", - "UIText_ChangeUser_HeaderTitle": "Manage Users", - "UIText_ChangeUser_PrimaryLabel": "Username to Add/Update", - "UIText_ChangeUser_SecondaryLabel": "New Password", - "UIText_ChangeUser_SecondaryPlaceholder": "Password", - "UIText_ChangeUser_SubmitButton": "Add/Update User" - } - }, - "BackendText": { - "gamemgr": { - "BackendText_ServerStarted": "Server started.", - "BackendText_ServerNotRunningOrAlreadyStopped": "Server was not running or was already stopped", - "BackendText_ServerStopped": "Server stopped." + "BackendText": { + "gamemgr": { + "BackendText_ServerStarted": "Server started.", + "BackendText_ServerNotRunningOrAlreadyStopped": "Server was not running or was already stopped", + "BackendText_ServerStopped": "Server stopped." + } } - }, - "nest1": { - "nestINnest1": {}, - "nestINnest2": {} - } -} \ No newline at end of file +} diff --git a/UIMod/onboard_bundled/localization/sv-SE.json b/UIMod/onboard_bundled/localization/sv-SE.json index 77784747..8d818c32 100644 --- a/UIMod/onboard_bundled/localization/sv-SE.json +++ b/UIMod/onboard_bundled/localization/sv-SE.json @@ -1,250 +1,255 @@ { - "UIText": { - "index": { - "UIText_StartButton": "Starta server", - "UIText_StopButton": "Stoppa server", - "UIText_Settings": "Redigera konfig", - "UIText_Update_SteamCMD": "Uppdatera server", - "UIText_Console": "Konsol", - "UIText_Detection_Events": "Detekteringshändelser", - "UIText_Backend_Log": "Backend Konsol", - "UIText_Backup_Manager": "Backup-hanterare", - "UIText_Connected_PlayersHeader": "Konnekterade spelare", - "UIText_Discord_Info": "Gå med i Discord och hjälp till att förbättra SSUI eller få support!", - "UIText_API_Info": "API-slutpunktsreferens", - "UIText_Copyright": "Upphovsrätt", - "UIText_Copyright1": "Licensierad under", - "UIText_Copyright2": "Proprietär licens" + "UIText": { + "index": { + "UIText_StartButton": "Starta server", + "UIText_StopButton": "Stoppa server", + "UIText_Settings": "Redigera konfig", + "UIText_Update_SteamCMD": "Uppdatera server", + "UIText_Console": "Konsol", + "UIText_Detection_Events": "Detekteringshändelser", + "UIText_Backend_Log": "Backend Konsol", + "UIText_Backup_Manager": "Backup-hanterare", + "UIText_Connected_PlayersHeader": "Konnekterade spelare", + "UIText_Discord_Info": "Gå med i Discord och hjälp till att förbättra SSUI eller få support!", + "UIText_API_Info": "API-slutpunktsreferens", + "UIText_Copyright": "Upphovsrätt", + "UIText_Copyright1": "Licensierad under", + "UIText_Copyright2": "Proprietär licens" + }, + "config": { + "UIText_ServerConfig": "Konfiguration", + "UIText_DiscordIntegration": "Discord-integration", + "UIText_DetectionManager": "Detektering", + "UIText_ConfigurationWizard": "Konfigurationsguide", + "UIText_PleaseSelectSection": "Välj en konfigurationssektion ovan", + "UIText_UseWizardAlternative": "Alternativt, använd konfigurationsguiden för att konfigurera servern.", + "UIText_BasicSettings": "Grund", + "UIText_NetworkSettings": "Nätverk", + "UIText_AdvancedSettings": "Avancerad", + "basic": { + "UIText_BasicServerSettings": "Grundläggande serverinställningar", + "UIText_ServerName": "Servernamn", + "UIText_ServerNameInfo": "Namn som visas i serverlistan", + "UIText_SaveFileName": "Sparfilsnamn", + "UIText_SaveFileNameInfo": "Namn på sparmappen. Måste börja med stor bokstav. För att skapa en ny värld, ange världstypen att generera. Vi rekommenderar att du använder guiden för att konfigurera detta korrekt.", + "UIText_SaveFileNameUseWizzardButtonText": "Öppna guiden", + "UIText_MaxPlayers": "Max spelare", + "UIText_MaxPlayersInfo": "Maximalt antal tillåtna spelare", + "UIText_ServerPassword": "Serverlösenord", + "UIText_ServerPasswordInfo": "Lämna tomt för inget lösenord", + "UIText_AdminPassword": "Adminlösenord", + "UIText_AdminPasswordInfo": "Lösenord för serveradministratör", + "UIText_AutoSave": "Autospara", + "UIText_AutoSaveInfo": "Sätt till TRUE för att aktivera automatisk sparning", + "UIText_SaveInterval": "Sparintervall", + "UIText_SaveIntervalInfo": "Tid i sekunder mellan sparanden. Rekommenderas att inte recede 60 sekunder.", + "UIText_AutoPauseServer": "Autopausa server", + "UIText_AutoPauseServerInfo": "Pausa servern automatiskt när inga spelare är anslutna" + }, + "network": { + "UIText_NetworkConfiguration": "Nätverkskonfiguration", + "UIText_GamePort": "Spelport", + "UIText_GamePortInfo": "Standard: 27016", + "UIText_UpdatePort": "Uppdateringsport", + "UIText_UpdatePortInfo": "Standard: 27015", + "UIText_UPNPEnabled": "UPNP aktiverad", + "UIText_UPNPEnabledInfo": "Aktivera automatisk UPNP-portvidarebefordran", + "UIText_LocalIpAddress": "Lokal IP-adress", + "UIText_LocalIpAddressInfo": "IP-adress att binda till", + "UIText_StartLocalHost": "Starta lokal värd", + "UIText_StartLocalHostInfo": "Sätt till TRUE. Detta är nödvändigt för att servern ska fungera.", + "UIText_ServerVisible": "Server synlig", + "UIText_ServerVisibleInfo": "Sätt till TRUE för att visa servern offentligt", + "UIText_UseSteamP2P": "Använd Steam P2P", + "UIText_UseSteamP2PInfo": "Aktivera Steam Peer-to-Peer-nätverk" + }, + "advanced": { + "UIText_AdvancedConfiguration": "Avancerad konfiguration", + "UIText_ServerAuthSecret": "Serverautentiseringshemlighet", + "UIText_ServerAuthSecretInfo": "Autentiseringshemlighet för servern (valfritt)", + "UIText_ServerExePath": "Sökväg till serverprogram", + "UIText_ServerExePathInfo": "Systemsökväg till serverprogrammet", + "UIText_ServerExePathInfo2": "Kan inte redigeras från gränssnittet av säkerhetsskäl, men du kan ändra det manuellt i config.json-filen.", + "UIText_AdditionalParams": "Ytterligare parametrar", + "UIText_AdditionalParamsInfo": "Format: AnpassadParam1 Värde1 AnpassadParam2 Värde2", + "UIText_AutoRestartServerTimer": "Schemalagd spelserveromstart", + "UIText_AutoRestartServerTimerInfo": "

Tidsram i minuter eller tidsformat (t.ex. 15:04 eller 03:04PM) för att schemalägga en automatisk omstart av spelservern. 0 = inaktiverad, 1440 = 24 timmar, etc. Du kommer att se meddelandet 'Observera, server startar om 30/20/10/5 sekunder!' i spelet före omstarten.

", + "UIText_GameBranch": "Spel-Branch", + "UIText_GameBranchInfo": "Spel-Branch att använda. Vid ändring krävs omstart av SSUI!", + "UIText_AllowAutoGameServerUpdates": "Aktivera automatiska uppdateringar av spelservern", + "UIText_AllowAutoGameServerUpdatesInfo": "Tillåt spelservern att automatiskt söka efter och uppdatera till den senaste versionen. Obs! Servern startas om när en ny version har hittats och installerats. Flera varningsmeddelanden skickas till servern med SAY-kommandon 60–10 sekunder före omstarten." + }, + "terrain": { + "UIText_UseNewTerrainAndSave": "Använd nytt system", + "UIText_Difficulty": "Svårighetsgrad", + "UIText_DifficultyInfo": "Svårighetsgrad för världsskapande. Standard är Normal om tomt.", + "UIText_StartCondition": "Startvillkor", + "UIText_StartConditionInfo": "Startvillkor för världsskapande. Standard är världstypens standardvillkor om tomt.", + "UIText_StartLocation": "Startplats", + "UIText_StartLocationInfo": "Startplats för världsskapande. Standard är DefaultStartLocation om tomt.", + "UIText_AutoStartServerOnStartup": "Starta servern automatiskt vid uppstart", + "UIText_AutoStartServerOnStartupInfo": "Starta spelservern automatiskt när SSUI startas. Standard är false.", + "UIText_TerrainSettingsHeader": "NYA TERRÄNG- OCH SPARANDE SYSTEMINSTÄLLNINGAR", + "UIText_TerrainWarning": "Dessa inställningar är endast användbara om du kör en version av Stationeers som är NYARE än september 2025. Gamla sparade spel är INTE kompatibla med det nya systemet, men kan migreras med JacksonTheMasters migreringsverktyg .. Relaterad information om \"hur man gör\" i FAQ där gäller även för dedikerade servrar.", + "UIText_UseNewTerrainAndSaveInfo": "Ställ in på TRUE för att aktivera hantering av .save-filer i Backup Manager och argumentanalys. Om inställningen är false fungerar endast Stationeers-versioner före terrängomarbetningen (≈ mitten av 2025). Standardinställningen är TRUE!" + }, + "discord": { + "UIText_DiscordIntegrationTitle": "Fördelar med Discord-integration", + "UIText_DiscordBotToken": "Discord-bot-token", + "UIText_DiscordBotTokenInfo": "Autentiseringstoken för din Discord-bot", + "UIText_ChannelConfiguration": "Kanalkonfiguration", + "UIText_AdminCommandChannel": "Admin-kommandokanal", + "UIText_AdminCommandChannelInfo": "Kanal för admin-kommandon", + "UIText_ControlPanelChannel": "Kontrollpanelkanal", + "UIText_ControlPanelChannelInfo": "Kanal för kontrollpanel", + "UIText_StatusChannel": "Statuskanal", + "UIText_StatusChannelInfo": "Uppdateringar om serverstatus", + "UIText_ConnectionListChannel": "Anslutningslistkanal", + "UIText_ConnectionListChannelInfo": "Spårning av spelaranslutningar", + "UIText_LogChannel": "Loggkanal", + "UIText_LogChannelInfo": "Utdata för serverloggar", + "UIText_SaveInfoChannel": "Sparinfokanal", + "UIText_SaveInfoChannelInfo": "Information om sparfiler", + "UIText_ErrorChannel": "Felkanal", + "UIText_ErrorChannelInfo": "Felmeddelanden från servern", + "UIText_BannedPlayersListPath": "Sökväg till bannlysta spelare", + "UIText_BannedPlayersListPathInfo": "Filsökväg till listan över bannlysta spelare", + "UIText_DiscordIntegrationBenefits": "Fördelar med Discord-integration", + "UIText_DiscordBenefit1": "Övervaka serverstatus i realtid", + "UIText_DiscordBenefit2": "Hantera omstarter och återställningar på distans", + "UIText_DiscordBenefit3": "Spåra spelaranslutningar", + "UIText_DiscordBenefit4": "Alternativ för community-hantering", + "UIText_DiscordBenefit5": "Felnotiser i realtid", + "UIText_DiscordSetupInstructions": "För installationsinstruktioner, besök" + }, + "UIText_TerrainSettings": "Ny terräng" + }, + "setup": { + "UIText_FooterText": "Behöver du hjälp? Kolla Stationeers Server UI Github Wiki.", + "UIText_FooterTextInfo": "Du kan avsluta guiden när som helst, varje steg sparas individuellt.", + "UIText_SSCM_FooterText": "Använd SSCM för den mest kraftfulla hanteringen av Stationeers-servrar! Du kan köra kommandon från webbkonsolen utan att störa vanliga funktioner!", + "UIText_Welcome_Title": "Stationeers Server UI", + "UIText_Welcome_HeaderTitle": "Välkommen!", + "UIText_Welcome_SubmitButton": "Börja konfigurera", + "UIText_Welcome_SkipButton": "Hoppa över konfiguration", + "UIText_PlsRead_Title": "Läs detta!", + "UIText_PlsRead_HeaderTitle": "Ansvarsfriskrivning", + "UIText_PlsRead_StepMessage": "Läs texterna ordentligt! De flesta rapporterade problem beror på felaktiga inställningar.", + "UIText_PlsRead_SubmitButton": "Jag förstår", + "UIText_PlsRead_SkipButton": "Jag förstår", + "UIText_ServerName_Title": "Stationeers Server UI", + "UIText_ServerName_HeaderTitle": "Servernamn", + "UIText_ServerName_StepMessage": "Ge din server ett namn, t.ex. 'Rymdstation 13'", + "UIText_ServerName_PrimaryPlaceholder": "Min Stationeers-server med UI", + "UIText_ServerName_PrimaryLabel": "Servernamn", + "UIText_ServerName_SubmitButton": "Spara & fortsätt", + "UIText_ServerName_SkipButton": "Hoppa över", + "UIText_SaveIdentifier_Title": "Stationeers Server UI", + "UIText_SaveIdentifier_HeaderTitle": "Sparfil", + "UIText_SaveIdentifier_StepMessage": "Ange ett namn för ditt spel och världstyp från alternativen nedan.", + "UIText_SaveIdentifier_PrimaryLabel": "Namn på din karta", + "UIText_SaveIdentifier_PrimaryPlaceholder": "MinStationeersKarta", + "UIText_SaveIdentifier_SecondaryLabel": "Stationeers världstyp", + "UIText_SaveIdentifier_SecondaryPlaceholder": "Klicka för att välja en världstyp", + "UIText_SaveIdentifier_SubmitButton": "Spara & fortsätt", + "UIText_SaveIdentifier_SkipButton": "Hoppa över", + "UIText_MaxPlayers_Title": "Stationeers Server UI", + "UIText_MaxPlayers_HeaderTitle": "Spelargräns", + "UIText_MaxPlayers_StepMessage": "Välj det maximala antalet spelare som kan ansluta till servern. Rekommenderas att inte överstiga 20", + "UIText_MaxPlayers_PrimaryPlaceholder": "8", + "UIText_MaxPlayers_PrimaryLabel": "Max spelare", + "UIText_MaxPlayers_SubmitButton": "Spara & fortsätt", + "UIText_MaxPlayers_SkipButton": "Hoppa över", + "UIText_ServerPassword_Title": "Stationeers Server UI", + "UIText_ServerPassword_HeaderTitle": "Serverlösenord", + "UIText_ServerPassword_StepMessage": "Ange ett serverlösenord eller hoppa över detta steg.", + "UIText_ServerPassword_PrimaryPlaceholder": "Serverlösenord", + "UIText_ServerPassword_PrimaryLabel": "Serverlösenord", + "UIText_ServerPassword_SubmitButton": "Spara & fortsätt", + "UIText_ServerPassword_SkipButton": "Hoppa över", + "UIText_GameBranch_Title": "Stationeers Server UI", + "UIText_GameBranch_HeaderTitle": "Spel-branch", + "UIText_GameBranch_StepMessage": "Ange en beta-branch eller hoppa över för att använda standardversionen. Om du byter brancher, se till att klicka på Uppdatera server på huvudpanelen efter att du har slutfört den här guiden.", + "UIText_GameBranch_SecondaryPlaceholder": "Välj en branch", + "UIText_GameBranch_SecondaryLabel": "Spelbranch", + "UIText_GameBranch_SubmitButton": "Spara & fortsätt", + "UIText_GameBranch_SkipButton": "Använd standardversion", + "UIText_NewTerrainAndSaveSystem_Title": "VIKTIGT", + "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Välj terrängsystem", + "UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder": "nej", + "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Aktivera nytt system", + "UIText_NewTerrainAndSaveSystem_SubmitButton": "Spara & fortsätt", + "UIText_NewTerrainAndSaveSystem_SkipButton": "Hoppa över", + "UIText_NetworkConfigChoice_Title": "Stationeers Server UI", + "UIText_NetworkConfigChoice_HeaderTitle": "Nätverkskonfiguration", + "UIText_NetworkConfigChoice_StepMessage": "Vill du konfigurera nätverksinställningar? Ange 'ja' för att konfigurera eller hoppa över för att använda standardvärden. Obs: Nätverkskonfiguration är särskilt viktigt på Linux-servrar.", + "UIText_NetworkConfigChoice_PrimaryPlaceholder": "ja", + "UIText_NetworkConfigChoice_PrimaryLabel": "Konfigurera nätverk", + "UIText_NetworkConfigChoice_SubmitButton": "Fortsätt", + "UIText_NetworkConfigChoice_SkipButton": "Hoppa över (använd standardvärden)", + "UIText_GamePort_Title": "Stationeers Server UI", + "UIText_GamePort_HeaderTitle": "Nätverk (1/4)", + "UIText_GamePort_StepMessage": "Ange portnummer för spelanslutningar", + "UIText_GamePort_PrimaryPlaceholder": "27016", + "UIText_GamePort_PrimaryLabel": "Spelport", + "UIText_GamePort_SubmitButton": "Spara & fortsätt", + "UIText_GamePort_SkipButton": "Hoppa över", + "UIText_UpdatePort_Title": "Stationeers Server UI", + "UIText_UpdatePort_HeaderTitle": "Nätverk (2/4)", + "UIText_UpdatePort_StepMessage": "Ange portnummer för uppdateringsanslutningar", + "UIText_UpdatePort_PrimaryPlaceholder": "27015", + "UIText_UpdatePort_PrimaryLabel": "Uppdateringsport", + "UIText_UpdatePort_SubmitButton": "Spara & fortsätt", + "UIText_UpdatePort_SkipButton": "Hoppa över", + "UIText_UPnPEnabled_Title": "Stationeers Server UI", + "UIText_UPnPEnabled_HeaderTitle": "Nätverk (3/4)", + "UIText_UPnPEnabled_StepMessage": "Aktivera UPnP? Ange 'ja' för att aktivera eller 'nej' för att inaktivera.", + "UIText_UPnPEnabled_PrimaryPlaceholder": "ja/nej", + "UIText_UPnPEnabled_PrimaryLabel": "Aktivera UPnP", + "UIText_UPnPEnabled_SubmitButton": "Spara & fortsätt", + "UIText_UPnPEnabled_SkipButton": "Hoppa över", + "UIText_LocalIPAddress_Title": "Stationeers Server UI", + "UIText_LocalIPAddress_HeaderTitle": "Nätverk (4/4)", + "UIText_LocalIPAddress_StepMessage": "Ange serverns lokala IP-adress i formatet 0.0.0.0 (ingen CIDR-notation)", + "UIText_LocalIPAddress_PrimaryPlaceholder": "0.0.0.0", + "UIText_LocalIPAddress_PrimaryLabel": "Lokal IP-adress", + "UIText_LocalIPAddress_SubmitButton": "Spara & fortsätt", + "UIText_LocalIPAddress_SkipButton": "Hoppa över", + "UIText_AdminAccount_Title": "Stationeers Server UI", + "UIText_AdminAccount_HeaderTitle": "Admin-konto", + "UIText_AdminAccount_StepMessage": "Konfigurera ditt admin-konto.", + "UIText_AdminAccount_PrimaryPlaceholder": "Användarnamn", + "UIText_AdminAccount_PrimaryLabel": "Användarnamn", + "UIText_AdminAccount_SecondaryLabel": "Lösenord", + "UIText_AdminAccount_SecondaryPlaceholder": "Lösenord", + "UIText_AdminAccount_SubmitButton": "Spara & fortsätt", + "UIText_AdminAccount_SkipButton": "Hoppa över autentisering", + "UIText_Finalize_Title": "Det var allt", + "UIText_Finalize_HeaderTitle": "Slutför konfiguration", + "UIText_Finalize_StepMessage": "Redo att slutföra? Din konfiguration har redan sparats under guiden. Om du vill ändra inställningar kan du klicka på Gå tillbaka till start och hoppa över det du vill behålla. De flesta inställningar kan också ändras i konfigurationsfliken i gränssnittet.", + "UIText_Finalize_SubmitButton": "Gå tillbaka till start", + "UIText_Finalize_SkipButton": "Hoppa över autentisering", + "UIText_Login_Title": "Stationeers Server UI", + "UIText_Login_HeaderTitle": "Logga in", + "UIText_Login_PrimaryLabel": "Användarnamn", + "UIText_Login_SecondaryLabel": "Lösenord", + "UIText_Login_PrimaryPlaceholder": "Ange användarnamn", + "UIText_Login_SecondaryPlaceholder": "Ange lösenord", + "UIText_Login_SubmitButton": "Logga in", + "UIText_ChangeUser_Title": "Stationeers Server UI", + "UIText_ChangeUser_HeaderTitle": "Hantera användare", + "UIText_ChangeUser_PrimaryLabel": "Användarnamn att lägga till/uppdatera", + "UIText_ChangeUser_SecondaryLabel": "Nytt lösenord", + "UIText_ChangeUser_SecondaryPlaceholder": "Lösenord", + "UIText_ChangeUser_SubmitButton": "Lägg till/uppdatera användare", + "UIText_NewTerrainAndSaveSystem_StepMessage": "Använder du en GAMMAL branch, såsom preterrain eller äldre utan förändringar i terrängsystemet? Om ja, inaktivera hanteringen av det nya terräng- och sparningssystemet här. Ange ”ja” eller hoppa över för att aktivera (standard) eller ”nej” för att använda det gamla sparnings- och terrängsystemet. Om du är osäker, hoppa över detta steg." + } }, - "config": { - "UIText_ServerConfig": "Konfiguration", - "UIText_DiscordIntegration": "Discord-integration", - "UIText_DetectionManager": "Detektering", - "UIText_ConfigurationWizard": "Konfigurationsguide", - "UIText_PleaseSelectSection": "Välj en konfigurationssektion ovan", - "UIText_UseWizardAlternative": "Alternativt, använd konfigurationsguiden för att konfigurera servern.", - "UIText_BasicSettings": "Grund", - "UIText_NetworkSettings": "Nätverk", - "UIText_AdvancedSettings": "Avancerad", - "basic": { - "UIText_BasicServerSettings": "Grundläggande serverinställningar", - "UIText_ServerName": "Servernamn", - "UIText_ServerNameInfo": "Namn som visas i serverlistan", - "UIText_SaveFileName": "Sparfilsnamn", - "UIText_SaveFileNameInfo": "Namn på sparmappen. Måste börja med stor bokstav. För att skapa en ny värld, ange världstypen att generera. Vi rekommenderar att du använder guiden för att konfigurera detta korrekt.", - "UIText_SaveFileNameUseWizzardButtonText": "Öppna guiden", - "UIText_MaxPlayers": "Max spelare", - "UIText_MaxPlayersInfo": "Maximalt antal tillåtna spelare", - "UIText_ServerPassword": "Serverlösenord", - "UIText_ServerPasswordInfo": "Lämna tomt för inget lösenord", - "UIText_AdminPassword": "Adminlösenord", - "UIText_AdminPasswordInfo": "Lösenord för serveradministratör", - "UIText_AutoSave": "Autospara", - "UIText_AutoSaveInfo": "Sätt till TRUE för att aktivera automatisk sparning", - "UIText_SaveInterval": "Sparintervall", - "UIText_SaveIntervalInfo": "Tid i sekunder mellan sparningar", - "UIText_AutoPauseServer": "Autopausa server", - "UIText_AutoPauseServerInfo": "Pausa servern automatiskt när inga spelare är anslutna" - }, - "network": { - "UIText_NetworkConfiguration": "Nätverkskonfiguration", - "UIText_GamePort": "Spelport", - "UIText_GamePortInfo": "Standard: 27016", - "UIText_UpdatePort": "Uppdateringsport", - "UIText_UpdatePortInfo": "Standard: 27015", - "UIText_UPNPEnabled": "UPNP aktiverad", - "UIText_UPNPEnabledInfo": "Aktivera automatisk UPNP-portvidarebefordran", - "UIText_LocalIpAddress": "Lokal IP-adress", - "UIText_LocalIpAddressInfo": "IP-adress att binda till", - "UIText_StartLocalHost": "Starta lokal värd", - "UIText_StartLocalHostInfo": "Sätt till TRUE. Detta är nödvändigt för att servern ska fungera.", - "UIText_ServerVisible": "Server synlig", - "UIText_ServerVisibleInfo": "Sätt till TRUE för att visa servern offentligt", - "UIText_UseSteamP2P": "Använd Steam P2P", - "UIText_UseSteamP2PInfo": "Aktivera Steam Peer-to-Peer-nätverk" - }, - "advanced": { - "UIText_AdvancedConfiguration": "Avancerad konfiguration", - "UIText_ServerAuthSecret": "Serverautentiseringshemlighet", - "UIText_ServerAuthSecretInfo": "Autentiseringshemlighet för servern (valfritt)", - "UIText_ServerExePath": "Sökväg till serverprogram", - "UIText_ServerExePathInfo": "Systemsökväg till serverprogrammet", - "UIText_ServerExePathInfo2": "Kan inte redigeras från gränssnittet av säkerhetsskäl, men du kan ändra det manuellt i config.json-filen.", - "UIText_AdditionalParams": "Ytterligare parametrar", - "UIText_AdditionalParamsInfo": "Format: AnpassadParam1 Värde1 AnpassadParam2 Värde2", - "UIText_AutoRestartServerTimer": "Schemalagd spelserveromstart", - "UIText_AutoRestartServerTimerInfo": "Tidsram i minuter för att schemalägga en automatisk spelserveromstart. 0 = inaktiverad, 1440 = 24 timmar, osv. Om SSCM är aktiverat visas meddelanden som \"Varning, servern startar om om 30/20/10/5 sekunder!\" i spelet före omstart.", - "UIText_GameBranch": "Spelgren", - "UIText_GameBranchInfo": "Spelgren att använda. Vid ändring krävs omstart av SSUI!", - "UIText_AllowAutoGameServerUpdates": "Aktivera automatiska uppdateringar av spelservern", - "UIText_AllowAutoGameServerUpdatesInfo": "Tillåt spelservern att automatiskt söka efter och uppdatera till den senaste versionen. Obs! Servern startas om när en ny version har hittats och installerats. Flera varningsmeddelanden skickas till servern med SAY-kommandon 60–10 sekunder före omstarten." - }, - "terrain": { - "UIText_UseNewTerrainAndSave": "Använd nytt system", - "UIText_Difficulty": "Svårighetsgrad", - "UIText_DifficultyInfo": "Svårighetsgrad för världsskapande. Standard är Normal om tomt.", - "UIText_StartCondition": "Startvillkor", - "UIText_StartConditionInfo": "Startvillkor för världsskapande. Standard är världstypens standardvillkor om tomt.", - "UIText_StartLocation": "Startplats", - "UIText_StartLocationInfo": "Startplats för världsskapande. Standard är DefaultStartLocation om tomt.", - "UIText_AutoStartServerOnStartup": "Starta servern automatiskt vid uppstart", - "UIText_AutoStartServerOnStartupInfo": "Starta spelservern automatiskt när SSUI startas. Standard är false." - }, - "discord": { - "UIText_DiscordIntegrationTitle": "Fördelar med Discord-integration", - "UIText_DiscordBotToken": "Discord-bot-token", - "UIText_DiscordBotTokenInfo": "Autentiseringstoken för din Discord-bot", - "UIText_ChannelConfiguration": "Kanalkonfiguration", - "UIText_AdminCommandChannel": "Admin-kommandokanal", - "UIText_AdminCommandChannelInfo": "Kanal för admin-kommandon", - "UIText_ControlPanelChannel": "Kontrollpanelkanal", - "UIText_ControlPanelChannelInfo": "Kanal för kontrollpanel", - "UIText_StatusChannel": "Statuskanal", - "UIText_StatusChannelInfo": "Uppdateringar om serverstatus", - "UIText_ConnectionListChannel": "Anslutningslistkanal", - "UIText_ConnectionListChannelInfo": "Spårning av spelaranslutningar", - "UIText_LogChannel": "Loggkanal", - "UIText_LogChannelInfo": "Utdata för serverloggar", - "UIText_SaveInfoChannel": "Sparinfokanal", - "UIText_SaveInfoChannelInfo": "Information om sparfiler", - "UIText_ErrorChannel": "Felkanal", - "UIText_ErrorChannelInfo": "Felmeddelanden från servern", - "UIText_BannedPlayersListPath": "Sökväg till bannlysta spelare", - "UIText_BannedPlayersListPathInfo": "Filsökväg till listan över bannlysta spelare", - "UIText_DiscordIntegrationBenefits": "Fördelar med Discord-integration", - "UIText_DiscordBenefit1": "Övervaka serverstatus i realtid", - "UIText_DiscordBenefit2": "Hantera omstarter och återställningar på distans", - "UIText_DiscordBenefit3": "Spåra spelaranslutningar", - "UIText_DiscordBenefit4": "Alternativ för community-hantering", - "UIText_DiscordBenefit5": "Felnotiser i realtid", - "UIText_DiscordSetupInstructions": "För installationsinstruktioner, besök" - } - }, - "setup": { - "UIText_FooterText": "Behöver du hjälp? Kolla Stationeers Server UI Github Wiki.", - "UIText_FooterTextInfo": "Du kan avsluta guiden när som helst, varje steg sparas individuellt.", - "UIText_SSCM_FooterText": "Använd SSCM för den mest kraftfulla hanteringen av Stationeers-servrar! Du kan köra kommandon från webbkonsolen utan att störa vanliga funktioner!", - "UIText_Welcome_Title": "Stationeers Server UI", - "UIText_Welcome_HeaderTitle": "Välkommen!", - "UIText_Welcome_SubmitButton": "Börja konfigurera", - "UIText_Welcome_SkipButton": "Hoppa över konfiguration", - "UIText_PlsRead_Title": "Läs detta!", - "UIText_PlsRead_HeaderTitle": "Viktigt", - "UIText_PlsRead_StepMessage": "Läs texterna ordentligt! De flesta rapporterade problem beror på felaktiga inställningar.", - "UIText_PlsRead_SubmitButton": "Jag förstår", - "UIText_PlsRead_SkipButton": "Jag förstår", - "UIText_ServerName_Title": "Stationeers Server UI", - "UIText_ServerName_HeaderTitle": "Servernamn", - "UIText_ServerName_StepMessage": "Ge din server ett namn, t.ex. 'Rymdstation 13'", - "UIText_ServerName_PrimaryPlaceholder": "Min Stationeers-server med UI", - "UIText_ServerName_PrimaryLabel": "Servernamn", - "UIText_ServerName_SubmitButton": "Spara & fortsätt", - "UIText_ServerName_SkipButton": "Hoppa över", - "UIText_SaveIdentifier_Title": "Stationeers Server UI", - "UIText_SaveIdentifier_HeaderTitle": "Sparfil", - "UIText_SaveIdentifier_StepMessage": "Ange ett namn för ditt spel och världstyp från alternativen nedan.", - "UIText_SaveIdentifier_PrimaryLabel": "Namn på din karta", - "UIText_SaveIdentifier_PrimaryPlaceholder": "MinStationeersKarta", - "UIText_SaveIdentifier_SecondaryLabel": "Stationeers världstyp", - "UIText_SaveIdentifier_SecondaryPlaceholder": "Klicka för att välja en världstyp", - "UIText_SaveIdentifier_SubmitButton": "Spara & fortsätt", - "UIText_SaveIdentifier_SkipButton": "Hoppa över", - "UIText_MaxPlayers_Title": "Stationeers Server UI", - "UIText_MaxPlayers_HeaderTitle": "Spelargräns", - "UIText_MaxPlayers_StepMessage": "Välj maximalt antal spelare som kan ansluta till servern.", - "UIText_MaxPlayers_PrimaryPlaceholder": "8", - "UIText_MaxPlayers_PrimaryLabel": "Max spelare", - "UIText_MaxPlayers_SubmitButton": "Spara & fortsätt", - "UIText_MaxPlayers_SkipButton": "Hoppa över", - "UIText_ServerPassword_Title": "Stationeers Server UI", - "UIText_ServerPassword_HeaderTitle": "Serverlösenord", - "UIText_ServerPassword_StepMessage": "Ange ett serverlösenord eller hoppa över detta steg.", - "UIText_ServerPassword_PrimaryPlaceholder": "Serverlösenord", - "UIText_ServerPassword_PrimaryLabel": "Serverlösenord", - "UIText_ServerPassword_SubmitButton": "Spara & fortsätt", - "UIText_ServerPassword_SkipButton": "Hoppa över", - "UIText_GameBranch_Title": "Stationeers Server UI", - "UIText_GameBranch_HeaderTitle": "Spel-branch", - "UIText_GameBranch_StepMessage": "Ange en betagren eller hoppa över för att använda standardversionen. Om du byter grenar, se till att klicka på Uppdatera server på huvudpanelen efter att du har slutfört den här guiden.", - "UIText_GameBranch_SecondaryPlaceholder": "Välj en gren", - "UIText_GameBranch_SecondaryLabel": "Spelgren", - "UIText_GameBranch_SubmitButton": "Spara & fortsätt", - "UIText_GameBranch_SkipButton": "Använd standardversion", - "UIText_NewTerrainAndSaveSystem_Title": "Viktigt", - "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Välj terrängsystem", - "UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder": "nej", - "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Aktivera nytt system", - "UIText_NewTerrainAndSaveSystem_SubmitButton": "Spara & fortsätt", - "UIText_NewTerrainAndSaveSystem_SkipButton": "Hoppa över", - "UIText_NetworkConfigChoice_Title": "Stationeers Server UI", - "UIText_NetworkConfigChoice_HeaderTitle": "Nätverk", - "UIText_NetworkConfigChoice_StepMessage": "Vill du konfigurera nätverksinställningar? Ange 'ja' för att konfigurera eller hoppa över för att använda standardvärden. Obs: Nätverkskonfiguration är särskilt viktigt på Linux-servrar.", - "UIText_NetworkConfigChoice_PrimaryPlaceholder": "ja", - "UIText_NetworkConfigChoice_PrimaryLabel": "Konfigurera nätverk", - "UIText_NetworkConfigChoice_SubmitButton": "Fortsätt", - "UIText_NetworkConfigChoice_SkipButton": "Hoppa över (använd standardvärden)", - "UIText_GamePort_Title": "Stationeers Server UI", - "UIText_GamePort_HeaderTitle": "Nätverk (1/4)", - "UIText_GamePort_StepMessage": "Ange portnummer för spelanslutningar", - "UIText_GamePort_PrimaryPlaceholder": "27016", - "UIText_GamePort_PrimaryLabel": "Spelport", - "UIText_GamePort_SubmitButton": "Spara & fortsätt", - "UIText_GamePort_SkipButton": "Hoppa över", - "UIText_UpdatePort_Title": "Stationeers Server UI", - "UIText_UpdatePort_HeaderTitle": "Nätverk (2/4)", - "UIText_UpdatePort_StepMessage": "Ange portnummer för uppdateringsanslutningar", - "UIText_UpdatePort_PrimaryPlaceholder": "27015", - "UIText_UpdatePort_PrimaryLabel": "Uppdateringsport", - "UIText_UpdatePort_SubmitButton": "Spara & fortsätt", - "UIText_UpdatePort_SkipButton": "Hoppa över", - "UIText_UPnPEnabled_Title": "Stationeers Server UI", - "UIText_UPnPEnabled_HeaderTitle": "Nätverk (3/4)", - "UIText_UPnPEnabled_StepMessage": "Aktivera UPnP? Ange 'ja' för att aktivera eller 'nej' för att inaktivera.", - "UIText_UPnPEnabled_PrimaryPlaceholder": "ja/nej", - "UIText_UPnPEnabled_PrimaryLabel": "Aktivera UPnP", - "UIText_UPnPEnabled_SubmitButton": "Spara & fortsätt", - "UIText_UPnPEnabled_SkipButton": "Hoppa över", - "UIText_LocalIPAddress_Title": "Stationeers Server UI", - "UIText_LocalIPAddress_HeaderTitle": "Nätverk (4/4)", - "UIText_LocalIPAddress_StepMessage": "Ange serverns lokala IP-adress i formatet 0.0.0.0 (ingen CIDR-notation)", - "UIText_LocalIPAddress_PrimaryPlaceholder": "0.0.0.0", - "UIText_LocalIPAddress_PrimaryLabel": "Lokal IP-adress", - "UIText_LocalIPAddress_SubmitButton": "Spara & fortsätt", - "UIText_LocalIPAddress_SkipButton": "Hoppa över", - "UIText_AdminAccount_Title": "Stationeers Server UI", - "UIText_AdminAccount_HeaderTitle": "Admin-konto", - "UIText_AdminAccount_StepMessage": "Konfigurera ditt admin-konto.", - "UIText_AdminAccount_PrimaryPlaceholder": "Användarnamn", - "UIText_AdminAccount_PrimaryLabel": "Användarnamn", - "UIText_AdminAccount_SecondaryLabel": "Lösenord", - "UIText_AdminAccount_SecondaryPlaceholder": "Lösenord", - "UIText_AdminAccount_SubmitButton": "Spara & fortsätt", - "UIText_AdminAccount_SkipButton": "Hoppa över autentisering", - "UIText_Finalize_Title": "Det var allt", - "UIText_Finalize_HeaderTitle": "Slutför konfiguration", - "UIText_Finalize_StepMessage": "Redo att slutföra? Din konfiguration har redan sparats under guiden. Om du vill ändra inställningar kan du klicka på Gå tillbaka till start och hoppa över det du vill behålla. De flesta inställningar kan också ändras i konfigurationsfliken i gränssnittet.", - "UIText_Finalize_SubmitButton": "Gå tillbaka till start", - "UIText_Finalize_SkipButton": "Hoppa över autentisering", - "UIText_Login_Title": "Stationeers Server UI", - "UIText_Login_HeaderTitle": "Logga in", - "UIText_Login_PrimaryLabel": "Användarnamn", - "UIText_Login_SecondaryLabel": "Lösenord", - "UIText_Login_PrimaryPlaceholder": "Ange användarnamn", - "UIText_Login_SecondaryPlaceholder": "Ange lösenord", - "UIText_Login_SubmitButton": "Logga in", - "UIText_ChangeUser_Title": "Stationeers Server UI", - "UIText_ChangeUser_HeaderTitle": "Hantera användare", - "UIText_ChangeUser_PrimaryLabel": "Användarnamn att lägga till/uppdatera", - "UIText_ChangeUser_SecondaryLabel": "Nytt lösenord", - "UIText_ChangeUser_SecondaryPlaceholder": "Lösenord", - "UIText_ChangeUser_SubmitButton": "Lägg till/uppdatera användare" - } - }, - "BackendText": { - "gamemgr": { - "BackendText_ServerStarted": "Server startad.", - "BackendText_ServerNotRunningOrAlreadyStopped": "Servern kördes inte eller var redan stoppad", - "BackendText_ServerStopped": "Server stoppad." + "BackendText": { + "gamemgr": { + "BackendText_ServerStarted": "Server startad.", + "BackendText_ServerNotRunningOrAlreadyStopped": "Servern kördes inte eller var redan stoppad", + "BackendText_ServerStopped": "Server stoppad." + } } - } -} \ No newline at end of file +} From a148b0281051095fdbb672d35f9ba109e352bdf7 Mon Sep 17 00:00:00 2001 From: SSUI Weblate Date: Wed, 24 Sep 2025 12:31:11 +0000 Subject: [PATCH 04/33] Translated using Weblate (German) Currently translated at 100.0% (231 of 231 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/v5/main/de/ --- UIMod/onboard_bundled/localization/de-DE.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UIMod/onboard_bundled/localization/de-DE.json b/UIMod/onboard_bundled/localization/de-DE.json index ad594471..e2b61504 100644 --- a/UIMod/onboard_bundled/localization/de-DE.json +++ b/UIMod/onboard_bundled/localization/de-DE.json @@ -22,15 +22,15 @@ "UIText_DetectionManager": "Erkennungsmanager", "UIText_ConfigurationWizard": "Konfigurations-Assistent", "UIText_PleaseSelectSection": "Bitte wähle oben eine Konfigurationssektion aus", - "UIText_UseWizardAlternative": "Alternativ nutze den Konfigurations-Assistenten zur Serverkonfiguration.", + "UIText_UseWizardAlternative": "Alternativ kannst du den Konfigurationsassistent zur Serverkonfiguration nutzen.", "UIText_BasicSettings": "Basis", "UIText_NetworkSettings": "Netzwerk", "UIText_AdvancedSettings": "Erweitert", "basic": { "UIText_BasicServerSettings": "Grundlegende Servereinstellungen", "UIText_ServerName": "Servername", - "UIText_ServerNameInfo": "Name in der Serverliste angezeigt", - "UIText_SaveFileName": "Speicherdatei Name", + "UIText_ServerNameInfo": "Name, der in der Serverliste angezeigt wird", + "UIText_SaveFileName": "Name der Speicherdatei", "UIText_SaveFileNameInfo": "Name des Speicherordners. Muss großgeschrieben sein. Für neue Welt, Welttyp angeben. Es wird empfohlen, diesen Wert über den Setup Assistent zu konfigurieren um ihn korrekt zu setzen. ", "UIText_SaveFileNameUseWizzardButtonText": "Öffne Assistent", "UIText_MaxPlayers": "Max Spieler", From c48568b5b23415fce495bf59fb55de1a22e09412 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Wed, 24 Sep 2025 15:58:03 +0200 Subject: [PATCH 05/33] fully migrate the old SaveInfo field into new vars if applicable and don't save SaveInfo back to config.json. --- src/config/config.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/config/config.go b/src/config/config.go index a1c97c25..5b1900fa 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -29,9 +29,9 @@ type JsonConfig struct { GameBranch string `json:"gameBranch"` GamePort string `json:"GamePort"` ServerName string `json:"ServerName"` - SaveInfo string `json:"SaveInfo"` // deprecated, kept for backwards compatibility - SaveName string `json:"SaveName"` // replaces SaveInfo - WorldID string `json:"WorldID"` // replaces SaveInfo + SaveInfo string `json:"SaveInfo,omitempty"` // deprecated, kept for backwards compatibility + SaveName string `json:"SaveName"` // replaces SaveInfo + WorldID string `json:"WorldID"` // replaces SaveInfo ServerMaxPlayers string `json:"ServerMaxPlayers"` ServerPassword string `json:"ServerPassword"` ServerAuthSecret string `json:"ServerAuthSecret"` @@ -169,7 +169,7 @@ func applyConfig(cfg *JsonConfig) { StartCondition = getString(cfg.StartCondition, "START_CONDITION", "") StartLocation = getString(cfg.StartLocation, "START_LOCATION", "") ServerName = getString(cfg.ServerName, "SERVER_NAME", "Stationeers Server UI") - SaveInfo = getString(cfg.SaveInfo, "SAVE_INFO", "") + SaveInfo = getString(cfg.SaveInfo, "SAVE_INFO", "") // deprecated, kept for backwards compatibility - if set, this gets migrated to SaveName and WorldID and the field is not written back to config.json SaveName = getString(cfg.SaveName, "SAVE_NAME", "MyMapName") WorldID = getString(cfg.WorldID, "WORLD_ID", "Lunar") ServerMaxPlayers = getString(cfg.ServerMaxPlayers, "SERVER_MAX_PLAYERS", "6") @@ -266,7 +266,7 @@ func applyConfig(cfg *JsonConfig) { cfg.AutoStartServerOnStartup = &autoStartServerOnStartupVal // Process SaveInfo to maintain backwards compatibility with pre-5.6.6 SaveInfo field (deprecated) - if SaveInfo != "" { + if SaveInfo != "" && SaveName == "" && WorldID == "" { parts := strings.Split(SaveInfo, " ") if len(parts) > 0 { SaveName = parts[0] @@ -276,6 +276,7 @@ func applyConfig(cfg *JsonConfig) { WorldID = parts[1] fmt.Println("WorldID: " + WorldID) } + cfg.SaveInfo = "" } // Set backup paths for old or new style saves @@ -295,7 +296,6 @@ func applyConfig(cfg *JsonConfig) { // use safeSaveConfig EXCLUSIVELY though setter functions // M U S T be called while holding a lock on ConfigMu! func safeSaveConfig() error { - fmt.Println("safeSaveConfig") cfg := JsonConfig{ DiscordToken: DiscordToken, ControlChannelID: ControlChannelID, @@ -321,7 +321,6 @@ func safeSaveConfig() error { StartCondition: StartCondition, StartLocation: StartLocation, ServerName: ServerName, - SaveInfo: SaveInfo, SaveName: SaveName, WorldID: WorldID, ServerMaxPlayers: ServerMaxPlayers, From 0249e458a62470d5f8b5ad7b06726d992f817348 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Wed, 24 Sep 2025 16:13:02 +0200 Subject: [PATCH 06/33] remove unused vars from config page --- src/web/configpage.go | 122 +++++++++++++++++++--------------------- src/web/templatevars.go | 122 +++++++++++++++++++--------------------- 2 files changed, 118 insertions(+), 126 deletions(-) diff --git a/src/web/configpage.go b/src/web/configpage.go index 90340314..b711a1cd 100644 --- a/src/web/configpage.go +++ b/src/web/configpage.go @@ -128,7 +128,6 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) { StartLocation: config.GetStartLocation(), ServerName: config.GetServerName(), SaveName: config.GetSaveName(), - SaveInfo: config.GetLegacySaveInfo(), WorldID: config.GetWorldID(), ServerMaxPlayers: config.GetServerMaxPlayers(), ServerPassword: config.GetServerPassword(), @@ -182,68 +181,65 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) { UIText_TerrainSettings: localization.GetString("UIText_TerrainSettings"), UIText_BasicServerSettings: localization.GetString("UIText_BasicServerSettings"), - UIText_ServerName: localization.GetString("UIText_ServerName"), - UIText_ServerNameInfo: localization.GetString("UIText_ServerNameInfo"), - UIText_SaveFileName: localization.GetString("UIText_SaveFileName"), - UIText_SaveFileNameInfo: localization.GetString("UIText_SaveFileNameInfo"), - UIText_SaveFileNameUseWizzardButtonText: localization.GetString("UIText_SaveFileNameUseWizzardButtonText"), - UIText_SaveName: localization.GetString("UIText_SaveName"), - UIText_SaveNameInfo: localization.GetString("UIText_SaveNameInfo"), - UIText_WorldID: localization.GetString("UIText_WorldID"), - UIText_WorldIDInfo: localization.GetString("UIText_WorldIDInfo"), - UIText_MaxPlayers: localization.GetString("UIText_MaxPlayers"), - UIText_MaxPlayersInfo: localization.GetString("UIText_MaxPlayersInfo"), - UIText_ServerPassword: localization.GetString("UIText_ServerPassword"), - UIText_ServerPasswordInfo: localization.GetString("UIText_ServerPasswordInfo"), - UIText_AdminPassword: localization.GetString("UIText_AdminPassword"), - UIText_AdminPasswordInfo: localization.GetString("UIText_AdminPasswordInfo"), - UIText_AutoSave: localization.GetString("UIText_AutoSave"), - UIText_AutoSaveInfo: localization.GetString("UIText_AutoSaveInfo"), - UIText_SaveInterval: localization.GetString("UIText_SaveInterval"), - UIText_SaveIntervalInfo: localization.GetString("UIText_SaveIntervalInfo"), - UIText_AutoPauseServer: localization.GetString("UIText_AutoPauseServer"), - UIText_AutoPauseServerInfo: localization.GetString("UIText_AutoPauseServerInfo"), - UIText_NetworkConfiguration: localization.GetString("UIText_NetworkConfiguration"), - UIText_GamePort: localization.GetString("UIText_GamePort"), - UIText_GamePortInfo: localization.GetString("UIText_GamePortInfo"), - UIText_UpdatePort: localization.GetString("UIText_UpdatePort"), - UIText_UpdatePortInfo: localization.GetString("UIText_UpdatePortInfo"), - UIText_UPNPEnabled: localization.GetString("UIText_UPNPEnabled"), - UIText_UPNPEnabledInfo: localization.GetString("UIText_UPNPEnabledInfo"), - UIText_LocalIpAddress: localization.GetString("UIText_LocalIpAddress"), - UIText_LocalIpAddressInfo: localization.GetString("UIText_LocalIpAddressInfo"), - UIText_StartLocalHost: localization.GetString("UIText_StartLocalHost"), - UIText_StartLocalHostInfo: localization.GetString("UIText_StartLocalHostInfo"), - UIText_ServerVisible: localization.GetString("UIText_ServerVisible"), - UIText_ServerVisibleInfo: localization.GetString("UIText_ServerVisibleInfo"), - UIText_UseSteamP2P: localization.GetString("UIText_UseSteamP2P"), - UIText_UseSteamP2PInfo: localization.GetString("UIText_UseSteamP2PInfo"), - UIText_AdvancedConfiguration: localization.GetString("UIText_AdvancedConfiguration"), - UIText_ServerAuthSecret: localization.GetString("UIText_ServerAuthSecret"), - UIText_ServerAuthSecretInfo: localization.GetString("UIText_ServerAuthSecretInfo"), - UIText_ServerExePath: localization.GetString("UIText_ServerExePath"), - UIText_ServerExePathInfo: localization.GetString("UIText_ServerExePathInfo"), - UIText_ServerExePathInfo2: localization.GetString("UIText_ServerExePathInfo2"), - UIText_AdditionalParams: localization.GetString("UIText_AdditionalParams"), - UIText_AdditionalParamsInfo: localization.GetString("UIText_AdditionalParamsInfo"), - UIText_AutoRestartServerTimer: localization.GetString("UIText_AutoRestartServerTimer"), - UIText_AutoRestartServerTimerInfo: localization.GetString("UIText_AutoRestartServerTimerInfo"), - UIText_GameBranch: localization.GetString("UIText_GameBranch"), - UIText_GameBranchInfo: localization.GetString("UIText_GameBranchInfo"), - UIText_TerrainSettingsHeader: localization.GetString("UIText_TerrainSettingsHeader"), - UIText_TerrainWarning: localization.GetString("UIText_TerrainWarning"), - UIText_UseNewTerrainAndSave: localization.GetString("UIText_UseNewTerrainAndSave"), - UIText_UseNewTerrainAndSaveInfo: localization.GetString("UIText_UseNewTerrainAndSaveInfo"), - UIText_Difficulty: localization.GetString("UIText_Difficulty"), - UIText_DifficultyInfo: localization.GetString("UIText_DifficultyInfo"), - UIText_StartCondition: localization.GetString("UIText_StartCondition"), - UIText_StartConditionInfo: localization.GetString("UIText_StartConditionInfo"), - UIText_StartLocation: localization.GetString("UIText_StartLocation"), - UIText_StartLocationInfo: localization.GetString("UIText_StartLocationInfo"), - UIText_AutoStartServerOnStartup: localization.GetString("UIText_AutoStartServerOnStartup"), - UIText_AutoStartServerOnStartupInfo: localization.GetString("UIText_AutoStartServerOnStartupInfo"), - UIText_AllowAutoGameServerUpdates: localization.GetString("UIText_AllowAutoGameServerUpdates"), - UIText_AllowAutoGameServerUpdatesInfo: localization.GetString("UIText_AllowAutoGameServerUpdatesInfo"), + UIText_ServerName: localization.GetString("UIText_ServerName"), + UIText_ServerNameInfo: localization.GetString("UIText_ServerNameInfo"), + UIText_SaveName: localization.GetString("UIText_SaveName"), + UIText_SaveNameInfo: localization.GetString("UIText_SaveNameInfo"), + UIText_WorldID: localization.GetString("UIText_WorldID"), + UIText_WorldIDInfo: localization.GetString("UIText_WorldIDInfo"), + UIText_MaxPlayers: localization.GetString("UIText_MaxPlayers"), + UIText_MaxPlayersInfo: localization.GetString("UIText_MaxPlayersInfo"), + UIText_ServerPassword: localization.GetString("UIText_ServerPassword"), + UIText_ServerPasswordInfo: localization.GetString("UIText_ServerPasswordInfo"), + UIText_AdminPassword: localization.GetString("UIText_AdminPassword"), + UIText_AdminPasswordInfo: localization.GetString("UIText_AdminPasswordInfo"), + UIText_AutoSave: localization.GetString("UIText_AutoSave"), + UIText_AutoSaveInfo: localization.GetString("UIText_AutoSaveInfo"), + UIText_SaveInterval: localization.GetString("UIText_SaveInterval"), + UIText_SaveIntervalInfo: localization.GetString("UIText_SaveIntervalInfo"), + UIText_AutoPauseServer: localization.GetString("UIText_AutoPauseServer"), + UIText_AutoPauseServerInfo: localization.GetString("UIText_AutoPauseServerInfo"), + UIText_NetworkConfiguration: localization.GetString("UIText_NetworkConfiguration"), + UIText_GamePort: localization.GetString("UIText_GamePort"), + UIText_GamePortInfo: localization.GetString("UIText_GamePortInfo"), + UIText_UpdatePort: localization.GetString("UIText_UpdatePort"), + UIText_UpdatePortInfo: localization.GetString("UIText_UpdatePortInfo"), + UIText_UPNPEnabled: localization.GetString("UIText_UPNPEnabled"), + UIText_UPNPEnabledInfo: localization.GetString("UIText_UPNPEnabledInfo"), + UIText_LocalIpAddress: localization.GetString("UIText_LocalIpAddress"), + UIText_LocalIpAddressInfo: localization.GetString("UIText_LocalIpAddressInfo"), + UIText_StartLocalHost: localization.GetString("UIText_StartLocalHost"), + UIText_StartLocalHostInfo: localization.GetString("UIText_StartLocalHostInfo"), + UIText_ServerVisible: localization.GetString("UIText_ServerVisible"), + UIText_ServerVisibleInfo: localization.GetString("UIText_ServerVisibleInfo"), + UIText_UseSteamP2P: localization.GetString("UIText_UseSteamP2P"), + UIText_UseSteamP2PInfo: localization.GetString("UIText_UseSteamP2PInfo"), + UIText_AdvancedConfiguration: localization.GetString("UIText_AdvancedConfiguration"), + UIText_ServerAuthSecret: localization.GetString("UIText_ServerAuthSecret"), + UIText_ServerAuthSecretInfo: localization.GetString("UIText_ServerAuthSecretInfo"), + UIText_ServerExePath: localization.GetString("UIText_ServerExePath"), + UIText_ServerExePathInfo: localization.GetString("UIText_ServerExePathInfo"), + UIText_ServerExePathInfo2: localization.GetString("UIText_ServerExePathInfo2"), + UIText_AdditionalParams: localization.GetString("UIText_AdditionalParams"), + UIText_AdditionalParamsInfo: localization.GetString("UIText_AdditionalParamsInfo"), + UIText_AutoRestartServerTimer: localization.GetString("UIText_AutoRestartServerTimer"), + UIText_AutoRestartServerTimerInfo: localization.GetString("UIText_AutoRestartServerTimerInfo"), + UIText_GameBranch: localization.GetString("UIText_GameBranch"), + UIText_GameBranchInfo: localization.GetString("UIText_GameBranchInfo"), + UIText_TerrainSettingsHeader: localization.GetString("UIText_TerrainSettingsHeader"), + UIText_TerrainWarning: localization.GetString("UIText_TerrainWarning"), + UIText_UseNewTerrainAndSave: localization.GetString("UIText_UseNewTerrainAndSave"), + UIText_UseNewTerrainAndSaveInfo: localization.GetString("UIText_UseNewTerrainAndSaveInfo"), + UIText_Difficulty: localization.GetString("UIText_Difficulty"), + UIText_DifficultyInfo: localization.GetString("UIText_DifficultyInfo"), + UIText_StartCondition: localization.GetString("UIText_StartCondition"), + UIText_StartConditionInfo: localization.GetString("UIText_StartConditionInfo"), + UIText_StartLocation: localization.GetString("UIText_StartLocation"), + UIText_StartLocationInfo: localization.GetString("UIText_StartLocationInfo"), + UIText_AutoStartServerOnStartup: localization.GetString("UIText_AutoStartServerOnStartup"), + UIText_AutoStartServerOnStartupInfo: localization.GetString("UIText_AutoStartServerOnStartupInfo"), + UIText_AllowAutoGameServerUpdates: localization.GetString("UIText_AllowAutoGameServerUpdates"), + UIText_AllowAutoGameServerUpdatesInfo: localization.GetString("UIText_AllowAutoGameServerUpdatesInfo"), UIText_DiscordIntegrationTitle: localization.GetString("UIText_DiscordIntegrationTitle"), UIText_DiscordBotToken: localization.GetString("UIText_DiscordBotToken"), diff --git a/src/web/templatevars.go b/src/web/templatevars.go index 20f21394..6a36f2f2 100644 --- a/src/web/templatevars.go +++ b/src/web/templatevars.go @@ -40,7 +40,6 @@ type ConfigTemplateData struct { StartCondition string StartLocation string ServerName string - SaveInfo string SaveName string WorldID string ServerMaxPlayers string @@ -94,68 +93,65 @@ type ConfigTemplateData struct { UIText_TerrainSettings string UIText_BasicServerSettings string - UIText_ServerName string - UIText_ServerNameInfo string - UIText_SaveFileName string - UIText_SaveFileNameInfo string - UIText_SaveFileNameUseWizzardButtonText string - UIText_SaveName string - UIText_SaveNameInfo string - UIText_WorldID string - UIText_WorldIDInfo string - UIText_MaxPlayers string - UIText_MaxPlayersInfo string - UIText_ServerPassword string - UIText_ServerPasswordInfo string - UIText_AdminPassword string - UIText_AdminPasswordInfo string - UIText_AutoSave string - UIText_AutoSaveInfo string - UIText_SaveInterval string - UIText_SaveIntervalInfo string - UIText_AutoPauseServer string - UIText_AutoPauseServerInfo string - UIText_NetworkConfiguration string - UIText_GamePort string - UIText_GamePortInfo string - UIText_UpdatePort string - UIText_UpdatePortInfo string - UIText_UPNPEnabled string - UIText_UPNPEnabledInfo string - UIText_LocalIpAddress string - UIText_LocalIpAddressInfo string - UIText_StartLocalHost string - UIText_StartLocalHostInfo string - UIText_ServerVisible string - UIText_ServerVisibleInfo string - UIText_UseSteamP2P string - UIText_UseSteamP2PInfo string - UIText_AdvancedConfiguration string - UIText_ServerAuthSecret string - UIText_ServerAuthSecretInfo string - UIText_ServerExePath string - UIText_ServerExePathInfo string - UIText_ServerExePathInfo2 string - UIText_AdditionalParams string - UIText_AdditionalParamsInfo string - UIText_AutoRestartServerTimer string - UIText_AutoRestartServerTimerInfo string - UIText_GameBranch string - UIText_GameBranchInfo string - UIText_TerrainSettingsHeader string - UIText_TerrainWarning string - UIText_UseNewTerrainAndSave string - UIText_UseNewTerrainAndSaveInfo string - UIText_Difficulty string - UIText_DifficultyInfo string - UIText_StartCondition string - UIText_StartConditionInfo string - UIText_StartLocation string - UIText_StartLocationInfo string - UIText_AutoStartServerOnStartup string - UIText_AutoStartServerOnStartupInfo string - UIText_AllowAutoGameServerUpdates string - UIText_AllowAutoGameServerUpdatesInfo string + UIText_ServerName string + UIText_ServerNameInfo string + UIText_SaveName string + UIText_SaveNameInfo string + UIText_WorldID string + UIText_WorldIDInfo string + UIText_MaxPlayers string + UIText_MaxPlayersInfo string + UIText_ServerPassword string + UIText_ServerPasswordInfo string + UIText_AdminPassword string + UIText_AdminPasswordInfo string + UIText_AutoSave string + UIText_AutoSaveInfo string + UIText_SaveInterval string + UIText_SaveIntervalInfo string + UIText_AutoPauseServer string + UIText_AutoPauseServerInfo string + UIText_NetworkConfiguration string + UIText_GamePort string + UIText_GamePortInfo string + UIText_UpdatePort string + UIText_UpdatePortInfo string + UIText_UPNPEnabled string + UIText_UPNPEnabledInfo string + UIText_LocalIpAddress string + UIText_LocalIpAddressInfo string + UIText_StartLocalHost string + UIText_StartLocalHostInfo string + UIText_ServerVisible string + UIText_ServerVisibleInfo string + UIText_UseSteamP2P string + UIText_UseSteamP2PInfo string + UIText_AdvancedConfiguration string + UIText_ServerAuthSecret string + UIText_ServerAuthSecretInfo string + UIText_ServerExePath string + UIText_ServerExePathInfo string + UIText_ServerExePathInfo2 string + UIText_AdditionalParams string + UIText_AdditionalParamsInfo string + UIText_AutoRestartServerTimer string + UIText_AutoRestartServerTimerInfo string + UIText_GameBranch string + UIText_GameBranchInfo string + UIText_TerrainSettingsHeader string + UIText_TerrainWarning string + UIText_UseNewTerrainAndSave string + UIText_UseNewTerrainAndSaveInfo string + UIText_Difficulty string + UIText_DifficultyInfo string + UIText_StartCondition string + UIText_StartConditionInfo string + UIText_StartLocation string + UIText_StartLocationInfo string + UIText_AutoStartServerOnStartup string + UIText_AutoStartServerOnStartupInfo string + UIText_AllowAutoGameServerUpdates string + UIText_AllowAutoGameServerUpdatesInfo string UIText_DiscordIntegrationTitle string UIText_DiscordBotToken string From de5a2e2feb24cc1ee77b672db73912154d06efe6 Mon Sep 17 00:00:00 2001 From: JLangisch Date: Wed, 24 Sep 2025 16:22:05 +0200 Subject: [PATCH 07/33] fix image name --- .docker/compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.docker/compose.yml b/.docker/compose.yml index 38e693bd..a57d4413 100644 --- a/.docker/compose.yml +++ b/.docker/compose.yml @@ -1,10 +1,10 @@ services: stationeers-server: - container_name: stationeers-server + container_name: stationeers-server-ui build: context: .. dockerfile: ./.docker/Dockerfile - image: stationeers-server-ui:latest + image: stationeersserverui:latest stdin_open: true tty: true deploy: @@ -28,4 +28,4 @@ services: restart: unless-stopped volumes: - app-data: \ No newline at end of file + app-data: From aa939303c894f62dd05e901077ef2c408c2544d5 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Wed, 24 Sep 2025 16:25:41 +0200 Subject: [PATCH 08/33] fix docker context in gh action --- .github/workflows/ghcr-build-nightly.yaml | 2 +- .github/workflows/ghcr-build-release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ghcr-build-nightly.yaml b/.github/workflows/ghcr-build-nightly.yaml index 7fcfe13e..8e0badb3 100644 --- a/.github/workflows/ghcr-build-nightly.yaml +++ b/.github/workflows/ghcr-build-nightly.yaml @@ -50,7 +50,7 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: . + context: .. file: ./.docker/Dockerfile platforms: linux/amd64 push: true diff --git a/.github/workflows/ghcr-build-release.yaml b/.github/workflows/ghcr-build-release.yaml index 560e0c05..7eb85095 100644 --- a/.github/workflows/ghcr-build-release.yaml +++ b/.github/workflows/ghcr-build-release.yaml @@ -49,7 +49,7 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: . + context: .. file: ./.docker/Dockerfile platforms: linux/amd64 push: true From e379d022ab209062753f7aef3b7d1196416cb630 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Wed, 24 Sep 2025 16:31:58 +0200 Subject: [PATCH 09/33] fix docker context in gh action --- .github/workflows/ghcr-build-nightly.yaml | 2 +- .github/workflows/ghcr-build-release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ghcr-build-nightly.yaml b/.github/workflows/ghcr-build-nightly.yaml index 8e0badb3..7fcfe13e 100644 --- a/.github/workflows/ghcr-build-nightly.yaml +++ b/.github/workflows/ghcr-build-nightly.yaml @@ -50,7 +50,7 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: .. + context: . file: ./.docker/Dockerfile platforms: linux/amd64 push: true diff --git a/.github/workflows/ghcr-build-release.yaml b/.github/workflows/ghcr-build-release.yaml index 7eb85095..560e0c05 100644 --- a/.github/workflows/ghcr-build-release.yaml +++ b/.github/workflows/ghcr-build-release.yaml @@ -49,7 +49,7 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: .. + context: . file: ./.docker/Dockerfile platforms: linux/amd64 push: true From fce41950b7a18135173770cd25370766b63161a8 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Thu, 25 Sep 2025 03:20:00 +0200 Subject: [PATCH 10/33] added en-US localization for new SaveName and WorldID ui options --- UIMod/onboard_bundled/localization/en-US.json | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/UIMod/onboard_bundled/localization/en-US.json b/UIMod/onboard_bundled/localization/en-US.json index 1deb7f4a..a5c08c44 100644 --- a/UIMod/onboard_bundled/localization/en-US.json +++ b/UIMod/onboard_bundled/localization/en-US.json @@ -45,7 +45,12 @@ "UIText_SaveInterval": "Save Interval", "UIText_SaveIntervalInfo": "Time in seconds between saves. Recommended to not recede 60 seconds.", "UIText_AutoPauseServer": "Auto Pause Server", - "UIText_AutoPauseServerInfo": "Automatically pause server when no players are connected" + "UIText_AutoPauseServerInfo": "Automatically pause server when no players are connected", + "UIText_SaveName": "Save Name", + "UIText_SaveNameInfo": "Name of the save folder, like 'MySave' or 'Europa Brutal' ", + "UIText_WorldID": "World ID", + "UIText_WorldIDInfo": "World ID used when creating a new world. For a list of world IDs, see the Dedicated Server Wiki or configure it easily from the setup wizard." + }, "network": { "UIText_NetworkConfiguration": "Network Configuration", @@ -181,6 +186,20 @@ "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Enable new System", "UIText_NewTerrainAndSaveSystem_SubmitButton": "Save & Continue", "UIText_NewTerrainAndSaveSystem_SkipButton": "Skip", + "UIText_SaveName_Title": "Stationeers Server UI", + "UIText_SaveName_HeaderTitle": "Save Name", + "UIText_SaveName_StepMessage": "Configure the name of the savegame. This is the name of the folder that will be created in the 'saves' folder.", + "UIText_SaveName_PrimaryLabel": "Savegame name", + "UIText_SaveName_PrimaryPlaceholder": "MySave", + "UIText_SaveName_SubmitButton": "Save & Continue", + "UIText_SaveName_SkipButton": "Skip", + "UIText_WorldID_Title": "Stationeers Server UI", + "UIText_WorldID_HeaderTitle": "Map Name", + "UIText_WorldID_StepMessage": "Select your preferred map to play on.", + "UIText_WorldID_SecondaryLabel": "Choose from the dropdown below", + "UIText_WorldID_SecondaryPlaceholder": "Select a map", + "UIText_WorldID_SubmitButton": "Save & Continue", + "UIText_WorldID_SkipButton": "Skip", "UIText_NetworkConfigChoice_Title": "Stationeers Server UI", "UIText_NetworkConfigChoice_HeaderTitle": "Network Configuration", "UIText_NetworkConfigChoice_StepMessage": "Do you want to configure network settings? Enter 'yes' to configure or Skip to use defaults. Note: Network configuration is especially important on Linux servers.", From f8d58ca53678e0c7867961c32efa03806fed08a3 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Thu, 25 Sep 2025 03:51:22 +0200 Subject: [PATCH 11/33] update terrain and save system step handling in TwoBoxFormand according localization strings --- UIMod/onboard_bundled/localization/en-US.json | 4 +- src/web/TwoBoxForm.go | 43 +++++++++++-------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/UIMod/onboard_bundled/localization/en-US.json b/UIMod/onboard_bundled/localization/en-US.json index a5c08c44..41577884 100644 --- a/UIMod/onboard_bundled/localization/en-US.json +++ b/UIMod/onboard_bundled/localization/en-US.json @@ -180,8 +180,8 @@ "UIText_GameBranch_SubmitButton": "Save & Continue", "UIText_GameBranch_SkipButton": "Use Normal Version", "UIText_NewTerrainAndSaveSystem_Title": "IMPORTANT", - "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Select Terrain System", - "UIText_NewTerrainAndSaveSystem_StepMessage": "Using an OLD branch, such as preterrain or older without the terrain system changes? If yes, disable handling of the new terrain and save system here. Enter 'yes' or skip to enable (default) or 'no' to use the old save and terrain system. If you are unsure, skip this step.", + "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Old Terrain and Save System", + "UIText_NewTerrainAndSaveSystem_StepMessage": "It appears you have selected an OLD branch, such as preterrain or older without the terrain and save system changes. We have already saved this setting for you, but please cosider using a current stationeers branch instead.", "UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder": "yes", "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Enable new System", "UIText_NewTerrainAndSaveSystem_SubmitButton": "Save & Continue", diff --git a/src/web/TwoBoxForm.go b/src/web/TwoBoxForm.go index 55073b07..d4fcfcd7 100644 --- a/src/web/TwoBoxForm.go +++ b/src/web/TwoBoxForm.go @@ -105,6 +105,12 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { {Display: "Mimas Herschel", Value: "MimasHerschel"}} } + worldIDNextStep := "max_players" + if config.GetGameBranch() != "public" && config.GetGameBranch() != "beta" { + worldIDNextStep = "newterrain_and_savesystem" + config.SetIsNewTerrainAndSaveSystem(false) + } + // Define all steps in a map for easy access and modification steps := map[string]Step{ "welcome": { @@ -143,21 +149,7 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { SubmitButtonText: localization.GetString("UIText_GameBranch_SubmitButton"), SkipButtonText: localization.GetString("UIText_GameBranch_SkipButton"), ConfigField: "gameBranch", - NextStep: "newterrain_and_savesystem", - }, - "newterrain_and_savesystem": { - ID: "newterrain_and_savesystem", - Title: localization.GetString("UIText_NewTerrainAndSaveSystem_Title"), - HeaderTitle: localization.GetString("UIText_NewTerrainAndSaveSystem_HeaderTitle"), - StepMessage: localization.GetString("UIText_NewTerrainAndSaveSystem_StepMessage"), - PrimaryPlaceholderText: localization.GetString("UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder"), - PrimaryLabel: localization.GetString("UIText_NewTerrainAndSaveSystem_PrimaryLabel"), - SecondaryLabel: "", - SecondaryLabelType: "hidden", - SubmitButtonText: localization.GetString("UIText_NewTerrainAndSaveSystem_SubmitButton"), - SkipButtonText: localization.GetString("UIText_NewTerrainAndSaveSystem_SkipButton"), - ConfigField: "IsNewTerrainAndSaveSystem", - NextStep: "server_name", + NextStep: "server_name", }, "server_name": { ID: "server_name", @@ -199,7 +191,21 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { SubmitButtonText: localization.GetString("UIText_WorldID_SubmitButton"), SkipButtonText: localization.GetString("UIText_WorldID_SkipButton"), ConfigField: "WorldID", - NextStep: "max_players", + NextStep: worldIDNextStep, + }, + "newterrain_and_savesystem": { + ID: "newterrain_and_savesystem", + Title: localization.GetString("UIText_NewTerrainAndSaveSystem_Title"), + HeaderTitle: localization.GetString("UIText_NewTerrainAndSaveSystem_HeaderTitle"), + StepMessage: localization.GetString("UIText_NewTerrainAndSaveSystem_StepMessage"), + PrimaryPlaceholderText: "", + PrimaryLabel: "", + SecondaryLabel: "", + SecondaryLabelType: "hidden", + SubmitButtonText: localization.GetString("UIText_NewTerrainAndSaveSystem_SubmitButton"), + SkipButtonText: localization.GetString("UIText_NewTerrainAndSaveSystem_SkipButton"), + ConfigField: "IsNewTerrainAndSaveSystem", + NextStep: "max_players", }, "max_players": { ID: "max_players", @@ -378,9 +384,8 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { data.Step = "welcome" } stepOrder := []string{ - "welcome", "pls_read", "game_branch", "newterrain_and_savesystem", "server_name", "save_name", "world_id", "max_players", - "server_password", - "discord_enabled", "discord_token", "control_panel_channel", "save_channel", + "welcome", "pls_read", "game_branch", "server_name", "save_name", "world_id", "max_players", + "server_password", "discord_enabled", "discord_token", "control_panel_channel", "save_channel", "log_channel", "connection_list_channel", "status_channel", "control_channel", "network_config_choice", "game_port", "update_port", "upnp_enabled", "local_ip_address", "admin_account", "finalize", From 6895451311e93c4a54d755164aa5d7f997a620bb Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Thu, 25 Sep 2025 14:01:40 +0200 Subject: [PATCH 12/33] this removes the terrain selection screen from setup entirely and now relies on the set game branch to determine terrain system. --- UIMod/onboard_bundled/localization/en-US.json | 7 ------ src/config/config.go | 6 +++++ src/web/TwoBoxForm.go | 22 +------------------ 3 files changed, 7 insertions(+), 28 deletions(-) diff --git a/UIMod/onboard_bundled/localization/en-US.json b/UIMod/onboard_bundled/localization/en-US.json index 41577884..6edf7797 100644 --- a/UIMod/onboard_bundled/localization/en-US.json +++ b/UIMod/onboard_bundled/localization/en-US.json @@ -179,13 +179,6 @@ "UIText_GameBranch_SecondaryLabel": "Game Branch", "UIText_GameBranch_SubmitButton": "Save & Continue", "UIText_GameBranch_SkipButton": "Use Normal Version", - "UIText_NewTerrainAndSaveSystem_Title": "IMPORTANT", - "UIText_NewTerrainAndSaveSystem_HeaderTitle": "Old Terrain and Save System", - "UIText_NewTerrainAndSaveSystem_StepMessage": "It appears you have selected an OLD branch, such as preterrain or older without the terrain and save system changes. We have already saved this setting for you, but please cosider using a current stationeers branch instead.", - "UIText_NewTerrainAndSaveSystem_PrimaryPlaceholder": "yes", - "UIText_NewTerrainAndSaveSystem_PrimaryLabel": "Enable new System", - "UIText_NewTerrainAndSaveSystem_SubmitButton": "Save & Continue", - "UIText_NewTerrainAndSaveSystem_SkipButton": "Skip", "UIText_SaveName_Title": "Stationeers Server UI", "UIText_SaveName_HeaderTitle": "Save Name", "UIText_SaveName_StepMessage": "Configure the name of the savegame. This is the name of the folder that will be created in the 'saves' folder.", diff --git a/src/config/config.go b/src/config/config.go index 5b1900fa..1f932c3a 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -279,6 +279,12 @@ func applyConfig(cfg *JsonConfig) { cfg.SaveInfo = "" } + if GameBranch != "public" && GameBranch != "beta" { + IsNewTerrainAndSaveSystem = false + } else { + IsNewTerrainAndSaveSystem = true + } + // Set backup paths for old or new style saves if IsNewTerrainAndSaveSystem { // use new new style autosave folder diff --git a/src/web/TwoBoxForm.go b/src/web/TwoBoxForm.go index d4fcfcd7..a3baf602 100644 --- a/src/web/TwoBoxForm.go +++ b/src/web/TwoBoxForm.go @@ -105,12 +105,6 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { {Display: "Mimas Herschel", Value: "MimasHerschel"}} } - worldIDNextStep := "max_players" - if config.GetGameBranch() != "public" && config.GetGameBranch() != "beta" { - worldIDNextStep = "newterrain_and_savesystem" - config.SetIsNewTerrainAndSaveSystem(false) - } - // Define all steps in a map for easy access and modification steps := map[string]Step{ "welcome": { @@ -191,21 +185,7 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { SubmitButtonText: localization.GetString("UIText_WorldID_SubmitButton"), SkipButtonText: localization.GetString("UIText_WorldID_SkipButton"), ConfigField: "WorldID", - NextStep: worldIDNextStep, - }, - "newterrain_and_savesystem": { - ID: "newterrain_and_savesystem", - Title: localization.GetString("UIText_NewTerrainAndSaveSystem_Title"), - HeaderTitle: localization.GetString("UIText_NewTerrainAndSaveSystem_HeaderTitle"), - StepMessage: localization.GetString("UIText_NewTerrainAndSaveSystem_StepMessage"), - PrimaryPlaceholderText: "", - PrimaryLabel: "", - SecondaryLabel: "", - SecondaryLabelType: "hidden", - SubmitButtonText: localization.GetString("UIText_NewTerrainAndSaveSystem_SubmitButton"), - SkipButtonText: localization.GetString("UIText_NewTerrainAndSaveSystem_SkipButton"), - ConfigField: "IsNewTerrainAndSaveSystem", - NextStep: "max_players", + NextStep: "max_players", }, "max_players": { ID: "max_players", From 3ed99329ec89f4ec8fbae015d3c6edcc905672ea Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Thu, 25 Sep 2025 15:43:05 +0200 Subject: [PATCH 13/33] LocalIpAddress now defaults to 0.0.0.0, realized in playtest --- src/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/config.go b/src/config/config.go index 5b1900fa..7953f5ac 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -196,7 +196,7 @@ func applyConfig(cfg *JsonConfig) { AutoPauseServer = autoPauseServerVal cfg.AutoPauseServer = &autoPauseServerVal - LocalIpAddress = getString(cfg.LocalIpAddress, "LOCAL_IP_ADDRESS", "") + LocalIpAddress = getString(cfg.LocalIpAddress, "LOCAL_IP_ADDRESS", "0.0.0.0") startLocalHostVal := getBool(cfg.StartLocalHost, "START_LOCAL_HOST", true) StartLocalHost = startLocalHostVal From c6d8215674cb330a9e5967b36ef10720d86d3e6b Mon Sep 17 00:00:00 2001 From: Sebastian Meier zu Biesen Date: Thu, 25 Sep 2025 17:33:19 +0200 Subject: [PATCH 14/33] Zipslip fix for restore and steamcmd install. --- src/managers/backupmgr/restore.go | 35 ++++++++++++++++++++++++------- src/steamcmd/steamcmd-helper.go | 34 +++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/managers/backupmgr/restore.go b/src/managers/backupmgr/restore.go index 2d3bcd9f..1a07a80b 100644 --- a/src/managers/backupmgr/restore.go +++ b/src/managers/backupmgr/restore.go @@ -83,25 +83,43 @@ func (m *BackupManager) RestoreBackup(index int) error { } defer r.Close() + // --- Safe extraction ------------------------------------------------- for _, f := range r.File { - path := filepath.Join(tempDir, f.Name) + // Sanitize the entry name – strip any leading / or .. components. + entryName := filepath.Clean(f.Name) + + // Skip empty names or names that contain '..' after cleaning. + if entryName == "." || entryName == ".." || strings.Contains(entryName, "..") { + // This entry would escape the target directory; reject it. + logger.Backup.Warn(fmt.Sprintf("Skipping potentially unsafe zip entry %q", f.Name)) + continue + } + + destPath := filepath.Join(tempDir, entryName) + // Ensure the destination is still inside tempDir. + if !strings.HasPrefix(filepath.Clean(destPath), filepath.Clean(tempDir)+string(os.PathSeparator)) { + logger.Backup.Warn(fmt.Sprintf("Skipping zip entry that would escape extraction dir: %q", f.Name)) + continue + } + if f.FileInfo().IsDir() { - if err := os.MkdirAll(path, f.Mode()); err != nil { + if err := os.MkdirAll(destPath, f.Mode()); err != nil { m.revertRestore(restoredFiles) - return fmt.Errorf("failed to create directory %s: %w", path, err) + return fmt.Errorf("failed to create directory %s: %w", destPath, err) } continue } - if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil { + // Create any missing parent directories. + if err := os.MkdirAll(filepath.Dir(destPath), os.ModePerm); err != nil { m.revertRestore(restoredFiles) - return fmt.Errorf("failed to create parent directory for %s: %w", path, err) + return fmt.Errorf("failed to create parent directory for %s: %w", destPath, err) } - outFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + outFile, err := os.OpenFile(destPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { m.revertRestore(restoredFiles) - return fmt.Errorf("failed to create file %s: %w", path, err) + return fmt.Errorf("failed to create file %s: %w", destPath, err) } rc, err := f.Open() @@ -115,11 +133,12 @@ func (m *BackupManager) RestoreBackup(index int) error { rc.Close() outFile.Close() m.revertRestore(restoredFiles) - return fmt.Errorf("failed to extract file %s: %w", path, err) + return fmt.Errorf("failed to extract file %s: %w", destPath, err) } rc.Close() outFile.Close() } + // -------------------------------------------------------------------- // Update world_meta.xml DateTime with current Windows file time using regex now := time.Now() diff --git a/src/steamcmd/steamcmd-helper.go b/src/steamcmd/steamcmd-helper.go index 23e2b977..617aeacb 100644 --- a/src/steamcmd/steamcmd-helper.go +++ b/src/steamcmd/steamcmd-helper.go @@ -20,6 +20,30 @@ import ( "github.com/JacksonTheMaster/StationeersServerUI/v5/src/logger" ) +// isRelSymlink ensures `link` resolves to a path within `root`. +// This way we can avoid directory traversal attacks via symlinks. +// isSymlinkInsideRoot checks that a symlink named `name` with target `link` +// can be safely created under `root` without escaping it. +func isSymlinkInsideRoot(name, link, root string) bool { + // 1. The symlink file itself must stay inside `root`. + targetPath := filepath.Join(root, name) + if !strings.HasPrefix(filepath.Clean(targetPath), root) { + return false + } + + // 2. Resolve the link *relative to the symlink’s directory*. + // Do NOT call EvalSymlinks – we only care about the *path*. + linkDir := filepath.Dir(targetPath) // dir where the symlink will live + abs := filepath.Clean(filepath.Join(linkDir, link)) // e.g. /tmp/extract/../etc/passwd → /etc/passwd + + // 3. Ensure the absolute target is still under `root`. + rel, err := filepath.Rel(root, abs) + if err != nil { + return false + } + return !strings.HasPrefix(rel, "..") && !strings.HasPrefix(abs, string(os.PathSeparator)) +} + // createSteamCMDDirectory creates the SteamCMD directory. func createSteamCMDDirectory(steamCMDDir string) error { if err := os.MkdirAll(steamCMDDir, os.ModePerm); err != nil { @@ -169,8 +193,16 @@ func untar(dest string, r io.Reader) error { return fmt.Errorf("failed to write file %s: %v", target, err) } case tar.TypeSymlink: + // `header.Name` = path to symlink (relative to dest) + // `header.Linkname` = symlink target (relative or absolute) + if !isSymlinkInsideRoot(header.Name, header.Linkname, dest) { + logger.Install.Warn(fmt.Sprintf("Skipping unsafe symlink %s → %s", header.Name, header.Linkname)) + return fmt.Errorf("symlink %s → %s points outside extraction root", header.Name, header.Linkname) + } + + // If we reach here, the symlink is safe if err := os.Symlink(header.Linkname, target); err != nil { - return fmt.Errorf("failed to create symlink %s: %v", target, err) + return fmt.Errorf("failed to create symlink %s → %s: %w", target, header.Linkname, err) } default: return fmt.Errorf("unknown type: %v in %s", header.Typeflag, header.Name) From b9d6a4969ae74eababb5a7bb8630db0d2809b338 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Thu, 25 Sep 2025 19:21:44 +0200 Subject: [PATCH 15/33] add debug when shutting down global backup manager --- src/managers/backupmgr/backupinterface.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/backupmgr/backupinterface.go b/src/managers/backupmgr/backupinterface.go index af8d857f..6262de2d 100644 --- a/src/managers/backupmgr/backupinterface.go +++ b/src/managers/backupmgr/backupinterface.go @@ -17,6 +17,7 @@ var activeHTTPHandlers []*HTTPHandler // InitGlobalBackupManager initializes the global backup manager instance func InitGlobalBackupManager(config BackupConfig) error { if GlobalBackupManager != nil { + logger.Backup.Debug("Shutting down global backup manager") GlobalBackupManager.Shutdown() } From 3d8df7268f7fdedfb10e3ccc7cfd49adc182273b Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Thu, 25 Sep 2025 19:45:23 +0200 Subject: [PATCH 16/33] add Initializing log for global backup manager --- src/managers/backupmgr/backupinterface.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/managers/backupmgr/backupinterface.go b/src/managers/backupmgr/backupinterface.go index 6262de2d..9ba78a72 100644 --- a/src/managers/backupmgr/backupinterface.go +++ b/src/managers/backupmgr/backupinterface.go @@ -21,6 +21,8 @@ func InitGlobalBackupManager(config BackupConfig) error { GlobalBackupManager.Shutdown() } + logger.Backup.Debug("Initializing global backup manager") + GlobalBackupManager = NewBackupManager(config) // Update all active HTTP handlers with the new manager From e80bc23de8d9ecf7f138ae5e53d7abca3a529b1a Mon Sep 17 00:00:00 2001 From: SSUI Weblate Date: Thu, 25 Sep 2025 18:10:10 +0000 Subject: [PATCH 17/33] Translated using Weblate (German) Currently translated at 100.0% (242 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/v5/main/de/ Translated using Weblate (German) Currently translated at 95.8% (232 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/v5/main/de/ Translated using Weblate (German) Currently translated at 95.8% (232 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/v5/main/de/ Translated using Weblate (German) Currently translated at 95.8% (232 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/v5/main/de/ Translated using Weblate (German) Currently translated at 95.8% (232 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/v5/main/de/ --- UIMod/onboard_bundled/localization/de-DE.json | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/UIMod/onboard_bundled/localization/de-DE.json b/UIMod/onboard_bundled/localization/de-DE.json index e2b61504..c68c2c8d 100644 --- a/UIMod/onboard_bundled/localization/de-DE.json +++ b/UIMod/onboard_bundled/localization/de-DE.json @@ -44,7 +44,11 @@ "UIText_SaveInterval": "Speicher Intervall", "UIText_SaveIntervalInfo": "Zeit in Sekunden zwischen Speichervorgängen. Sollte 60 Sekunden nicht unterschreiten.", "UIText_AutoPauseServer": "Server Auto Pausieren", - "UIText_AutoPauseServerInfo": "Server automatisch pausieren wenn keine Spieler verbunden" + "UIText_AutoPauseServerInfo": "Server automatisch pausieren wenn keine Spieler verbunden", + "UIText_SaveName": "Savefile Name", + "UIText_SaveNameInfo": "Name des Speicherordners, z. B. „MySave“ oder „Europa Brutal“ ", + "UIText_WorldID": "Welt-ID", + "UIText_WorldIDInfo": "Die Welt-ID, die beim Erstellen einer neuen Welt benutzt wird. Eine Liste der Welt-IDs findest du im Dedicated Server Wiki oder kannst du ganz einfach über den Einrichtungsassistenten konfigurieren." }, "network": { "UIText_NetworkConfiguration": "Netzwerk Konfiguration", @@ -244,7 +248,21 @@ "UIText_ChangeUser_SecondaryLabel": "Neues Passwort", "UIText_ChangeUser_SecondaryPlaceholder": "Passwort", "UIText_ChangeUser_SubmitButton": "Benutzer Hinzufügen/Aktualisieren", - "UIText_NewTerrainAndSaveSystem_StepMessage": "Verwenden Sie einen ALTEN Branch, wie z. B. preterrain oder älter, ohne die Änderungen am Geländesystem? Wenn ja, deaktivieren Sie hier die Verarbeitung des neuen Geländes und Speichersystems. Geben Sie „yes” ein oder überspringen Sie diesen Schritt, um die Funktion zu aktivieren (Standard), oder „no”, um das alte Speicher- und Geländesystem zu verwenden. Wenn Sie sich nicht sicher sind, überspringen Sie diesen Schritt." + "UIText_NewTerrainAndSaveSystem_StepMessage": "Verwenden Sie einen ALTEN Branch, wie z. B. preterrain oder älter, ohne die Änderungen am Geländesystem? Wenn ja, deaktivieren Sie hier die Verarbeitung des neuen Geländes und Speichersystems. Geben Sie „yes” ein oder überspringen Sie diesen Schritt, um die Funktion zu aktivieren (Standard), oder „no”, um das alte Speicher- und Geländesystem zu verwenden. Wenn Sie sich nicht sicher sind, überspringen Sie diesen Schritt.", + "UIText_SaveName_HeaderTitle": "Savefile Name", + "UIText_SaveName_StepMessage": "Gib den Namen für den Spielstand ein. Das ist der Name des Ordners, der im Ordner „saves“ angelegt wird.", + "UIText_SaveName_PrimaryLabel": "Name des Spielstands", + "UIText_SaveName_Title": "Stationeers Server UI", + "UIText_SaveName_PrimaryPlaceholder": "MeineWelt", + "UIText_SaveName_SubmitButton": "Speichern & Weiter", + "UIText_SaveName_SkipButton": "Überspringen", + "UIText_WorldID_Title": "Stationeers Server UI", + "UIText_WorldID_HeaderTitle": "Name der Karte", + "UIText_WorldID_StepMessage": "Such dir deine Lieblingskarte aus, auf der du spielen willst.", + "UIText_WorldID_SecondaryLabel": "Wähle aus dem Dropdown-Menü unten aus", + "UIText_WorldID_SecondaryPlaceholder": "Wähle eine Karte aus", + "UIText_WorldID_SubmitButton": "Speichern & Weiter", + "UIText_WorldID_SkipButton": "Überspringen" } }, "BackendText": { From 08f1c81631135a560d44597258524e47b18f3617 Mon Sep 17 00:00:00 2001 From: SSUI Weblate Date: Thu, 25 Sep 2025 18:10:10 +0000 Subject: [PATCH 18/33] Translated using Weblate (Swedish) Currently translated at 93.8% (227 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/stationeersserverui/main/sv/ Translated using Weblate (Swedish) Currently translated at 93.8% (227 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/stationeersserverui/main/sv/ Translated using Weblate (Swedish) Currently translated at 93.3% (226 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/stationeersserverui/main/sv/ Translated using Weblate (Swedish) Currently translated at 93.3% (226 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/stationeersserverui/main/sv/ Translated using Weblate (Swedish) Currently translated at 93.3% (226 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/stationeersserverui/main/sv/ --- UIMod/onboard_bundled/localization/sv-SE.json | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/UIMod/onboard_bundled/localization/sv-SE.json b/UIMod/onboard_bundled/localization/sv-SE.json index 8d818c32..9cc5d994 100644 --- a/UIMod/onboard_bundled/localization/sv-SE.json +++ b/UIMod/onboard_bundled/localization/sv-SE.json @@ -44,7 +44,11 @@ "UIText_SaveInterval": "Sparintervall", "UIText_SaveIntervalInfo": "Tid i sekunder mellan sparanden. Rekommenderas att inte recede 60 sekunder.", "UIText_AutoPauseServer": "Autopausa server", - "UIText_AutoPauseServerInfo": "Pausa servern automatiskt när inga spelare är anslutna" + "UIText_AutoPauseServerInfo": "Pausa servern automatiskt när inga spelare är anslutna", + "UIText_SaveName": "Sparfil namn", + "UIText_SaveNameInfo": "Namnet på den sparade mappen, till exempel \"MySave\" eller \"Europa Brutal\" ", + "UIText_WorldID": "Världs-ID", + "UIText_WorldIDInfo": "" }, "network": { "UIText_NetworkConfiguration": "Nätverkskonfiguration", @@ -242,7 +246,21 @@ "UIText_ChangeUser_SecondaryLabel": "Nytt lösenord", "UIText_ChangeUser_SecondaryPlaceholder": "Lösenord", "UIText_ChangeUser_SubmitButton": "Lägg till/uppdatera användare", - "UIText_NewTerrainAndSaveSystem_StepMessage": "Använder du en GAMMAL branch, såsom preterrain eller äldre utan förändringar i terrängsystemet? Om ja, inaktivera hanteringen av det nya terräng- och sparningssystemet här. Ange ”ja” eller hoppa över för att aktivera (standard) eller ”nej” för att använda det gamla sparnings- och terrängsystemet. Om du är osäker, hoppa över detta steg." + "UIText_NewTerrainAndSaveSystem_StepMessage": "Använder du en GAMMAL branch, såsom preterrain eller äldre utan förändringar i terrängsystemet? Om ja, inaktivera hanteringen av det nya terräng- och sparningssystemet här. Ange ”ja” eller hoppa över för att aktivera (standard) eller ”nej” för att använda det gamla sparnings- och terrängsystemet. Om du är osäker, hoppa över detta steg.", + "UIText_SaveName_Title": "", + "UIText_SaveName_HeaderTitle": "", + "UIText_SaveName_StepMessage": "", + "UIText_SaveName_PrimaryLabel": "", + "UIText_SaveName_PrimaryPlaceholder": "", + "UIText_SaveName_SubmitButton": "", + "UIText_SaveName_SkipButton": "", + "UIText_WorldID_Title": "", + "UIText_WorldID_HeaderTitle": "", + "UIText_WorldID_StepMessage": "", + "UIText_WorldID_SecondaryLabel": "", + "UIText_WorldID_SecondaryPlaceholder": "", + "UIText_WorldID_SubmitButton": "", + "UIText_WorldID_SkipButton": "" } }, "BackendText": { From f648a10e40b9d7181e3b51e326cee0514790e04b Mon Sep 17 00:00:00 2001 From: SSUI Weblate Date: Thu, 25 Sep 2025 18:10:10 +0000 Subject: [PATCH 19/33] Translated using Weblate (English) Currently translated at 100.0% (242 of 242 strings) Translation: StationeersServerUI/Nightly Translate-URL: https://translate.ssui.dev/projects/stationeersserverui/main/en/ --- UIMod/onboard_bundled/localization/en-US.json | 1 - 1 file changed, 1 deletion(-) diff --git a/UIMod/onboard_bundled/localization/en-US.json b/UIMod/onboard_bundled/localization/en-US.json index 6edf7797..8412aea5 100644 --- a/UIMod/onboard_bundled/localization/en-US.json +++ b/UIMod/onboard_bundled/localization/en-US.json @@ -50,7 +50,6 @@ "UIText_SaveNameInfo": "Name of the save folder, like 'MySave' or 'Europa Brutal' ", "UIText_WorldID": "World ID", "UIText_WorldIDInfo": "World ID used when creating a new world. For a list of world IDs, see the Dedicated Server Wiki or configure it easily from the setup wizard." - }, "network": { "UIText_NetworkConfiguration": "Network Configuration", From 76bf0ed1c77cffc57a2627620726392cf72f0692 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 26 Sep 2025 04:48:28 +0200 Subject: [PATCH 20/33] removed reload message from loader --- src/core/loader/loader.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/loader/loader.go b/src/core/loader/loader.go index 1e64959a..6c224cc4 100644 --- a/src/core/loader/loader.go +++ b/src/core/loader/loader.go @@ -65,7 +65,6 @@ func ReloadBackupManager() { logger.Backup.Error("Failed to reload backup manager: " + err.Error()) return } - logger.Backup.Info("Backup manager reloaded successfully") } func ReloadDiscordBot() { From ff6bce9ff9116b56923066b82e8f79407ba807fb Mon Sep 17 00:00:00 2001 From: Sebastian Meier zu Biesen Date: Fri, 26 Sep 2025 14:25:25 +0200 Subject: [PATCH 21/33] Add validation for world configurations and enhance tooltip styles --- UIMod/onboard_bundled/assets/css/config.css | 58 ++++++++----- UIMod/onboard_bundled/assets/js/config.js | 92 +++++++++++++++++++++ UIMod/onboard_bundled/ui/config.html | 2 + 3 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 UIMod/onboard_bundled/assets/js/config.js diff --git a/UIMod/onboard_bundled/assets/css/config.css b/UIMod/onboard_bundled/assets/css/config.css index dc13f33e..d36b27a3 100644 --- a/UIMod/onboard_bundled/assets/css/config.css +++ b/UIMod/onboard_bundled/assets/css/config.css @@ -4,30 +4,31 @@ /* Wizard Button */ .wizard-button-container { display: flex; - justify-content: center; - margin-bottom: 25px; -} - -.wizard-button { - display: flex; - align-items: center; - background-color: rgba(0, 255, 171, 0.15); - border: 2px solid var(--primary); - border-radius: 12px; - padding: 12px 24px; - font-family: 'Press Start 2P', cursive; - font-size: 0.9rem; - letter-spacing: 1px; - transition: all 0.3s ease; +/* Tooltip styles */ +[title] { position: relative; - overflow: hidden; - z-index: 1; - box-shadow: 0 0 15px rgba(0, 255, 171, 0.3); + cursor: help; } -.wizard-button::before { - content: ''; +[title]:hover::before { + content: attr(title); position: absolute; + bottom: 100%; + left: 50%; + transform: translateX(-50%); + padding: 8px; + background-color: rgba(0, 0, 0, 0.9); + color: var(--primary); + border-radius: 4px; + font-size: 0.85em; + white-space: pre-line; + z-index: 1000; + box-shadow: 0 0 10px rgba(0, 255, 171, 0.2); + border: 1px solid var(--primary); + pointer-events: none; + min-width: 200px; + text-align: center; +} top: 0; left: -100%; width: 100%; @@ -365,4 +366,21 @@ select option { .feature-list li:hover { transform: translateX(3px); background-color: rgba(0, 0, 0, 0.4); +} + +.invalid { + border-color: #ff4d4d !important; + box-shadow: 0 0 10px rgba(255, 77, 77, 0.2); +} + +.invalid:focus { + box-shadow: 0 0 15px rgba(255, 77, 77, 0.4); +} + +.valid-options { + font-size: 0.85rem; + color: var(--primary); + margin-top: 5px; + font-family: 'Share Tech Mono', monospace; + opacity: 0.8; } \ No newline at end of file diff --git a/UIMod/onboard_bundled/assets/js/config.js b/UIMod/onboard_bundled/assets/js/config.js new file mode 100644 index 00000000..8988c314 --- /dev/null +++ b/UIMod/onboard_bundled/assets/js/config.js @@ -0,0 +1,92 @@ +// Validation configuration object +const worldConfigs = { + Lunar: { + conditions: ['DefaultStart', 'Brutal'], + locations: ['LunarSpawnCraterVesper', 'LunarSpawnMontesUmbrarum', 'LunarSpawnCraterNox', 'LunarSpawnMonsArcanus'] + }, + Mars2: { + conditions: ['DefaultStart', 'Brutal'], + locations: ['MarsSpawnCanyonOverlook', 'MarsSpawnButchersFlat', 'MarsSpawnFindersCanyon', 'MarsSpawnHellasCrags', 'MarsSpawnDonutFlats'] + }, + Europa3: { + conditions: ['EuropaDefault', 'EuropaBrutal'], + locations: ['EuropaSpawnIcyBasin', 'EuropaSpawnGlacialChannel', 'EuropaSpawnBalgatanPass', 'EuropaSpawnFrigidHighlands', 'EuropaSpawnTyreValley'] + }, + MimasHerschel: { + conditions: ['MimasDefault', 'MimasBrutal'], + locations: ['MimasSpawnCentralMesa', 'MimasSpawnHarrietCrater', 'MimasSpawnCraterField', 'MimasSpawnDustBowl'] + }, + Vulcan: { + conditions: ['VulcanDefault', 'VulcanBrutal'], + locations: ['VulcanSpawnVestaValley', 'VulcanSpawnEtnasFury', 'VulcanSpawnIxionsDemise', 'VulcanSpawnTitusReach'] + }, + Venus: { + conditions: ['VenusDefault', 'VulcanBrutal'], + locations: ['VenusSpawnGaiaValley', 'VenusSpawnDaisyValley', 'VenusSpawnFaithValley', 'VenusSpawnDuskValley'] + } +}; + +const validDifficulties = ['Creative', 'Easy', 'Normal', 'Stationeer']; + +// Get form elements +const worldIdInput = document.getElementById('WorldID'); +const difficultyInput = document.getElementById('Difficulty'); +const startConditionInput = document.getElementById('StartCondition'); +const startLocationInput = document.getElementById('StartLocation'); + +// Function to validate inputs +function validateInputs() { + const selectedWorld = worldIdInput.value; + const worldConfig = worldConfigs[selectedWorld]; + + // Reset all validation states + [worldIdInput, difficultyInput, startConditionInput, startLocationInput].forEach(input => { + input.classList.remove('invalid'); + const infoDiv = input.nextElementSibling; + if (infoDiv && infoDiv.classList.contains('input-info')) { + infoDiv.textContent = infoDiv.getAttribute('data-original-text') || infoDiv.textContent; + } + }); + + // Validate difficulty + if (!validDifficulties.includes(difficultyInput.value)) { + difficultyInput.classList.add('invalid'); + updateInfoText(difficultyInput, `Valid options: ${validDifficulties.join(', ')}`); + } + + if (worldConfig) { + // Validate start condition + if (!worldConfig.conditions.includes(startConditionInput.value)) { + startConditionInput.classList.add('invalid'); + updateInfoText(startConditionInput, `Valid options for ${selectedWorld}: ${worldConfig.conditions.join(', ')}`); + } + + // Validate start location + if (!worldConfig.locations.includes(startLocationInput.value)) { + startLocationInput.classList.add('invalid'); + updateInfoText(startLocationInput, `Valid options for ${selectedWorld}: ${worldConfig.locations.join(', ')}`); + } + } else if (selectedWorld) { + worldIdInput.classList.add('invalid'); + updateInfoText(worldIdInput, `Valid worlds: ${Object.keys(worldConfigs).join(', ')}`); + } +} + +function updateInfoText(input, text) { + const infoDiv = input.nextElementSibling; + if (infoDiv && infoDiv.classList.contains('input-info')) { + if (!infoDiv.getAttribute('data-original-text')) { + infoDiv.setAttribute('data-original-text', infoDiv.textContent); + } + infoDiv.textContent = text; + } +} + +// Add event listeners +worldIdInput.addEventListener('change', validateInputs); +difficultyInput.addEventListener('change', validateInputs); +startConditionInput.addEventListener('change', validateInputs); +startLocationInput.addEventListener('change', validateInputs); + +// Initialize validation on page load +document.addEventListener('DOMContentLoaded', validateInputs); \ No newline at end of file diff --git a/UIMod/onboard_bundled/ui/config.html b/UIMod/onboard_bundled/ui/config.html index 9c82fe6c..e300dc39 100644 --- a/UIMod/onboard_bundled/ui/config.html +++ b/UIMod/onboard_bundled/ui/config.html @@ -85,6 +85,7 @@

{{.UIText_BasicServerSettings}}

{{.UIText_WorldIDInfo}}
+
Valid worlds: Lunar, Mars2, Europa3, MimasHerschel, Vulcan, Venus
@@ -459,6 +460,7 @@

{{.UIText_DiscordIntegrationBenefits}}

}); + \ No newline at end of file From 42645601d3413237df532f1fb53529598778f488 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 26 Sep 2025 05:49:40 +0200 Subject: [PATCH 22/33] Enhance backup manager with thread-safe initialization and improved logging using UUID to track instances --- src/managers/backupmgr/backupinterface.go | 33 +++++++---- src/managers/backupmgr/manager.go | 69 ++++++++++++++--------- src/managers/backupmgr/restore.go | 2 +- src/managers/backupmgr/types.go | 1 + src/managers/backupmgr/watcher.go | 14 ++--- 5 files changed, 75 insertions(+), 44 deletions(-) diff --git a/src/managers/backupmgr/backupinterface.go b/src/managers/backupmgr/backupinterface.go index 9ba78a72..1772850c 100644 --- a/src/managers/backupmgr/backupinterface.go +++ b/src/managers/backupmgr/backupinterface.go @@ -1,11 +1,12 @@ -// backupinterface.go package backupmgr import ( + "sync" "time" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/config" "github.com/JacksonTheMaster/StationeersServerUI/v5/src/logger" + "github.com/google/uuid" ) // GlobalBackupManager is the singleton instance of the backup manager @@ -14,16 +15,25 @@ var GlobalBackupManager *BackupManager // Track all HTTP handlers that need updating when manager changes var activeHTTPHandlers []*HTTPHandler +// initMutex ensures thread-safe initialization of the global backup manager +var initMutex sync.Mutex + // InitGlobalBackupManager initializes the global backup manager instance func InitGlobalBackupManager(config BackupConfig) error { + // Lock to prevent concurrent initialization + initMutex.Lock() + defer initMutex.Unlock() + + // Shut down existing manager if it exists if GlobalBackupManager != nil { - logger.Backup.Debug("Shutting down global backup manager") + logger.Backup.Debugf("%s Previous Backup manager found. Shutting it down.", config.Identifier) GlobalBackupManager.Shutdown() + GlobalBackupManager = nil // Clear the manager to avoid stale references } - logger.Backup.Debug("Initializing global backup manager") - - GlobalBackupManager = NewBackupManager(config) + logger.Backup.Debugf("%s Creating a global backup manager with ID %s", config.Identifier, config.Identifier) + manager := NewBackupManager(config) + GlobalBackupManager = manager // Update all active HTTP handlers with the new manager for _, handler := range activeHTTPHandlers { @@ -31,13 +41,13 @@ func InitGlobalBackupManager(config BackupConfig) error { } // Start the backup manager in a goroutine to avoid blocking - go func() { - if err := GlobalBackupManager.Start(); err != nil { - logger.Backup.Error("Failed to start global backup manager: " + err.Error()) + go func(m *BackupManager) { + if err := m.Start(config.Identifier); err != nil { + logger.Backup.Warnf("%s Exited: "+err.Error(), config.Identifier) } - }() + }(manager) - // Return immediately, initialization will complete in the background + logger.Backup.Infof("%s Backup manager reloaded successfully", config.Identifier) return nil } @@ -49,6 +59,8 @@ func RegisterHTTPHandler(handler *HTTPHandler) { // GetBackupConfig returns a properly configured BackupConfig func GetBackupConfig() BackupConfig { + uuid := uuid.New() + bmIdentifier := "[BM" + uuid.String()[:6] + "]:" return BackupConfig{ WorldName: config.GetSaveName(), BackupDir: config.GetConfiguredBackupDir(), @@ -61,6 +73,7 @@ func GetBackupConfig() BackupConfig { KeepMonthlyFor: config.GetBackupKeepMonthlyFor(), CleanupInterval: config.GetBackupCleanupInterval(), }, + Identifier: bmIdentifier, } } diff --git a/src/managers/backupmgr/manager.go b/src/managers/backupmgr/manager.go index 1b908c84..af101704 100644 --- a/src/managers/backupmgr/manager.go +++ b/src/managers/backupmgr/manager.go @@ -23,44 +23,55 @@ can coexist but may conflict if configured with overlapping directories. // Initialize checks for BackupDir and waits until it exists, then ensures SafeBackupDir exists. // It returns a channel that signals when initialization is complete or an error occurs. -func (m *BackupManager) Initialize() <-chan error { +func (m *BackupManager) Initialize(bmIdentifier string) <-chan error { m.mu.Lock() defer m.mu.Unlock() result := make(chan error, 1) go func() { + defer close(result) const timeout = 90 * time.Minute const pollInterval = 2500 * time.Millisecond deadline := time.Now().Add(timeout) // Wait for BackupDir to exist - for { - if _, err := os.Stat(m.config.BackupDir); err == nil { - // Directory exists, proceed - break + for time.Now().Before(deadline) { + if stat, err := os.Stat(m.config.BackupDir); err == nil { + if stat.IsDir() { + // Directory exists, proceed + logger.Backup.Debugf("%s found backup directory: %s", bmIdentifier, m.config.BackupDir) + break + } + result <- fmt.Errorf("%s backup path %s is not a directory", bmIdentifier, m.config.BackupDir) + return } else if !os.IsNotExist(err) { // An error other than "not exists" occurred - result <- fmt.Errorf("error checking backup directory %s: %v", m.config.BackupDir, err) + result <- fmt.Errorf("%s error checking backup directory %s: %v", bmIdentifier, m.config.BackupDir, err) return } - if time.Now().After(deadline) { - result <- fmt.Errorf("timeout waiting for backup directory %s to be created", m.config.BackupDir) + logger.Backup.Debugf("%s waiting for save folder "+m.config.BackupDir+" to be created by Stationeers...", bmIdentifier) + select { + case <-m.ctx.Done(): + result <- fmt.Errorf("%s I have to go, the config was likely changed: %s", bmIdentifier, m.ctx.Err()) return + case <-time.After(pollInterval): + // Continue polling } - logger.Backup.Debug("Backup manager waiting for save folder " + m.config.BackupDir + " to be created by Stationeers...") + } - // Wait before checking again - time.Sleep(pollInterval) + if time.Now().After(deadline) { + result <- fmt.Errorf("%s timeout waiting for backup directory %s to be created", bmIdentifier, m.config.BackupDir) + return } // Ensure SafeBackupDir exists, create it if it doesn't if err := os.MkdirAll(m.config.SafeBackupDir, os.ModePerm); err != nil { - result <- fmt.Errorf("error creating safe backup directory %s: %v", m.config.SafeBackupDir, err) + result <- fmt.Errorf("%s error creating safe backup directory %s: %v", bmIdentifier, m.config.SafeBackupDir, err) return } - logger.Backup.Debug("Backup manager created safebackups dir successfully") + logger.Backup.Debugf("%s created safebackups at %s", bmIdentifier, m.config.SafeBackupDir) result <- nil }() @@ -69,22 +80,24 @@ func (m *BackupManager) Initialize() <-chan error { } // Start begins the backup monitoring and cleanup routines -func (m *BackupManager) Start() error { +func (m *BackupManager) Start(Identifier string) error { // Wait for initialization to complete - logger.Backup.Debug("Backup manager is waiting for save folder initialization...") - initResult := <-m.Initialize() + bmIdentifier := Identifier + + logger.Backup.Debugf("%s is waiting for save folder initialization...", bmIdentifier) + initResult := <-m.Initialize(bmIdentifier) if initResult != nil { - return fmt.Errorf("failed to initialize backup manager: %w", initResult) + return fmt.Errorf("%s failed to initialize backup manager : %w", bmIdentifier, initResult) } - logger.Backup.Info("Backup manager started") + logger.Backup.Infof("%s Backup manager instance started", bmIdentifier) // Start file watcher - watcher, err := newFsWatcher(m.config.BackupDir) + watcher, err := newFsWatcher(m.config.BackupDir, bmIdentifier) if err != nil { return fmt.Errorf("failed to create autosave watcher: %w", err) } m.watcher = watcher - go m.watchBackups() + go m.watchBackups(Identifier) if config.GetIsCleanupEnabled() { go m.startCleanupRoutine() @@ -94,30 +107,31 @@ func (m *BackupManager) Start() error { } // watchBackups monitors the backup directory for new files -func (m *BackupManager) watchBackups() { +func (m *BackupManager) watchBackups(Identifier string) { m.wg.Add(1) defer m.wg.Done() - logger.Backup.Debug("Starting backup file watcher...") - defer logger.Backup.Debug("Backup file watcher stopped") + logger.Backup.Debugf("%s Starting backup file watcher...", Identifier) + defer logger.Backup.Debugf("%s Backup file watcher stopped", Identifier) for { select { case <-m.ctx.Done(): + logger.Backup.Debugf("%s WatchBackups stopped due to context cancellation", Identifier) return case event, ok := <-m.watcher.events: if !ok { return } if event.Op&fsnotify.Create == fsnotify.Create { - logger.Backup.Info("New backup file detected: " + event.Name) + logger.Backup.Infof("%s New backup file detected: %s", Identifier, event.Name) m.handleNewBackup(event.Name) } case err, ok := <-m.watcher.errors: if !ok { return } - logger.Backup.Error("Backup watcher error: " + err.Error()) + logger.Backup.Errorf("%s Backup watcher error: %s", Identifier, err.Error()) } } } @@ -178,6 +192,7 @@ func (m *BackupManager) startCleanupRoutine() { for { select { case <-m.ctx.Done(): + logger.Backup.Debug("Cleanup routine stopped due to context cancellation") return case <-ticker.C: if err := m.Cleanup(); err != nil { @@ -212,17 +227,19 @@ func (m *BackupManager) ListBackups(limit int) ([]BackupGroup, error) { // Shutdown stops all backup operations func (m *BackupManager) Shutdown() { - logger.Backup.Debug("Shutting down backup manager...") + logger.Backup.Debug("Shutting down previous backup manager...") m.mu.Lock() if m.cancel != nil { m.cancel() m.cancel = nil + logger.Backup.Debug("Context canceled for previous backup manager") } if m.watcher != nil { m.watcher.close() m.watcher = nil + logger.Backup.Debug("File watcher closed") } m.mu.Unlock() diff --git a/src/managers/backupmgr/restore.go b/src/managers/backupmgr/restore.go index 1a07a80b..51dfeafd 100644 --- a/src/managers/backupmgr/restore.go +++ b/src/managers/backupmgr/restore.go @@ -17,7 +17,7 @@ import ( func (m *BackupManager) RestoreBackup(index int) error { m.mu.Lock() defer m.mu.Unlock() - logger.Backup.Info("Restoring backup with index " + fmt.Sprintf("%d", index)) + logger.Backup.Infof("Restoring backup with index %s", fmt.Sprintf("%d", index)) groups, err := m.getBackupGroups() if err != nil { diff --git a/src/managers/backupmgr/types.go b/src/managers/backupmgr/types.go index c7e4503f..b4b48b8b 100644 --- a/src/managers/backupmgr/types.go +++ b/src/managers/backupmgr/types.go @@ -17,6 +17,7 @@ type BackupConfig struct { SafeBackupDir string RetentionPolicy RetentionPolicy WaitTime time.Duration + Identifier string } // RetentionPolicy defines backup retention rules diff --git a/src/managers/backupmgr/watcher.go b/src/managers/backupmgr/watcher.go index 4cc00c9f..a131c2e4 100644 --- a/src/managers/backupmgr/watcher.go +++ b/src/managers/backupmgr/watcher.go @@ -19,16 +19,16 @@ type fsWatcher struct { } // newFsWatcher creates a new file system watcher -func newFsWatcher(path string) (*fsWatcher, error) { +func newFsWatcher(path string, Identifier string) (*fsWatcher, error) { // Normalize path normalizedPath := filepath.Clean(path) - logger.Backup.Debug("Creating watcher for path: " + normalizedPath) + logger.Backup.Debugf("%s Creating watcher for path: %s ", Identifier, normalizedPath) watcher, err := fsnotify.NewWatcher() if err != nil { - return nil, fmt.Errorf("failed to create watcher: %w", err) + return nil, fmt.Errorf("%s failed to create watcher: %w", Identifier, err) } - logger.Backup.Debug("Watcher created successfully") + logger.Backup.Debugf("%s Watcher created successfully", Identifier) // Watch the root save path and all subdirectories err = filepath.WalkDir(normalizedPath, func(subPath string, d os.DirEntry, err error) error { @@ -37,16 +37,16 @@ func newFsWatcher(path string) (*fsWatcher, error) { } if d.IsDir() { if err := watcher.Add(subPath); err != nil { - logger.Backup.Error("Failed to add subdir to watcher: " + subPath + ": " + err.Error()) + logger.Backup.Errorf("%s Failed to add subdir %s to watcher: %s ", Identifier, subPath, err.Error()) } else { - logger.Backup.Debug("Successfully watching subdir: " + subPath) + logger.Backup.Debugf("%s Added subdir %s to watcher", Identifier, subPath) } } return nil }) if err != nil { watcher.Close() - return nil, fmt.Errorf("failed to add paths to watcher: %w", err) + return nil, fmt.Errorf("%s failed to add subdirectories to watcher: %w", Identifier, err) } w := &fsWatcher{ From 4cbb71ae5b8cc63e991a9f4d49f18dbc6cd11481 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:31:51 +0200 Subject: [PATCH 23/33] Update backup manager for consistency in variable naming and improved logging format --- src/managers/backupmgr/backupinterface.go | 4 +- src/managers/backupmgr/manager.go | 45 +++++++++++------------ src/managers/backupmgr/restore.go | 2 +- src/managers/backupmgr/watcher.go | 14 +++---- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/managers/backupmgr/backupinterface.go b/src/managers/backupmgr/backupinterface.go index 1772850c..6f0964be 100644 --- a/src/managers/backupmgr/backupinterface.go +++ b/src/managers/backupmgr/backupinterface.go @@ -59,8 +59,8 @@ func RegisterHTTPHandler(handler *HTTPHandler) { // GetBackupConfig returns a properly configured BackupConfig func GetBackupConfig() BackupConfig { - uuid := uuid.New() - bmIdentifier := "[BM" + uuid.String()[:6] + "]:" + id := uuid.New() + bmIdentifier := "[BM" + id.String()[:6] + "]:" return BackupConfig{ WorldName: config.GetSaveName(), BackupDir: config.GetConfiguredBackupDir(), diff --git a/src/managers/backupmgr/manager.go b/src/managers/backupmgr/manager.go index af101704..69338718 100644 --- a/src/managers/backupmgr/manager.go +++ b/src/managers/backupmgr/manager.go @@ -23,7 +23,7 @@ can coexist but may conflict if configured with overlapping directories. // Initialize checks for BackupDir and waits until it exists, then ensures SafeBackupDir exists. // It returns a channel that signals when initialization is complete or an error occurs. -func (m *BackupManager) Initialize(bmIdentifier string) <-chan error { +func (m *BackupManager) Initialize(identifier string) <-chan error { m.mu.Lock() defer m.mu.Unlock() @@ -40,21 +40,21 @@ func (m *BackupManager) Initialize(bmIdentifier string) <-chan error { if stat, err := os.Stat(m.config.BackupDir); err == nil { if stat.IsDir() { // Directory exists, proceed - logger.Backup.Debugf("%s found backup directory: %s", bmIdentifier, m.config.BackupDir) + logger.Backup.Debugf("%s found backup directory: %s", identifier, m.config.BackupDir) break } - result <- fmt.Errorf("%s backup path %s is not a directory", bmIdentifier, m.config.BackupDir) + result <- fmt.Errorf("%s backup path %s is not a directory", identifier, m.config.BackupDir) return } else if !os.IsNotExist(err) { // An error other than "not exists" occurred - result <- fmt.Errorf("%s error checking backup directory %s: %v", bmIdentifier, m.config.BackupDir, err) + result <- fmt.Errorf("%s error checking backup directory %s: %v", identifier, m.config.BackupDir, err) return } - logger.Backup.Debugf("%s waiting for save folder "+m.config.BackupDir+" to be created by Stationeers...", bmIdentifier) + logger.Backup.Debugf("%s waiting for save folder "+m.config.BackupDir+" to be created by Stationeers...", identifier) select { case <-m.ctx.Done(): - result <- fmt.Errorf("%s I have to go, the config was likely changed: %s", bmIdentifier, m.ctx.Err()) + result <- fmt.Errorf("%s I have to go, the config was likely changed: %s", identifier, m.ctx.Err()) return case <-time.After(pollInterval): // Continue polling @@ -62,16 +62,16 @@ func (m *BackupManager) Initialize(bmIdentifier string) <-chan error { } if time.Now().After(deadline) { - result <- fmt.Errorf("%s timeout waiting for backup directory %s to be created", bmIdentifier, m.config.BackupDir) + result <- fmt.Errorf("%s timeout waiting for backup directory %s to be created", identifier, m.config.BackupDir) return } // Ensure SafeBackupDir exists, create it if it doesn't if err := os.MkdirAll(m.config.SafeBackupDir, os.ModePerm); err != nil { - result <- fmt.Errorf("%s error creating safe backup directory %s: %v", bmIdentifier, m.config.SafeBackupDir, err) + result <- fmt.Errorf("%s error creating safe backup directory %s: %v", identifier, m.config.SafeBackupDir, err) return } - logger.Backup.Debugf("%s created safebackups at %s", bmIdentifier, m.config.SafeBackupDir) + logger.Backup.Debugf("%s created safebackups at %s", identifier, m.config.SafeBackupDir) result <- nil }() @@ -80,24 +80,23 @@ func (m *BackupManager) Initialize(bmIdentifier string) <-chan error { } // Start begins the backup monitoring and cleanup routines -func (m *BackupManager) Start(Identifier string) error { +func (m *BackupManager) Start(identifier string) error { // Wait for initialization to complete - bmIdentifier := Identifier - logger.Backup.Debugf("%s is waiting for save folder initialization...", bmIdentifier) - initResult := <-m.Initialize(bmIdentifier) + logger.Backup.Debugf("%s is waiting for save folder initialization...", identifier) + initResult := <-m.Initialize(identifier) if initResult != nil { - return fmt.Errorf("%s failed to initialize backup manager : %w", bmIdentifier, initResult) + return fmt.Errorf("%s failed to initialize backup manager : %w", identifier, initResult) } - logger.Backup.Infof("%s Backup manager instance started", bmIdentifier) + logger.Backup.Infof("%s Backup manager instance started", identifier) // Start file watcher - watcher, err := newFsWatcher(m.config.BackupDir, bmIdentifier) + watcher, err := newFsWatcher(m.config.BackupDir, identifier) if err != nil { return fmt.Errorf("failed to create autosave watcher: %w", err) } m.watcher = watcher - go m.watchBackups(Identifier) + go m.watchBackups(identifier) if config.GetIsCleanupEnabled() { go m.startCleanupRoutine() @@ -107,31 +106,31 @@ func (m *BackupManager) Start(Identifier string) error { } // watchBackups monitors the backup directory for new files -func (m *BackupManager) watchBackups(Identifier string) { +func (m *BackupManager) watchBackups(identifier string) { m.wg.Add(1) defer m.wg.Done() - logger.Backup.Debugf("%s Starting backup file watcher...", Identifier) - defer logger.Backup.Debugf("%s Backup file watcher stopped", Identifier) + logger.Backup.Debugf("%s Starting backup file watcher...", identifier) + defer logger.Backup.Debugf("%s Backup file watcher stopped", identifier) for { select { case <-m.ctx.Done(): - logger.Backup.Debugf("%s WatchBackups stopped due to context cancellation", Identifier) + logger.Backup.Debugf("%s WatchBackups stopped due to context cancellation", identifier) return case event, ok := <-m.watcher.events: if !ok { return } if event.Op&fsnotify.Create == fsnotify.Create { - logger.Backup.Infof("%s New backup file detected: %s", Identifier, event.Name) + logger.Backup.Infof("%s New backup file detected: %s", identifier, event.Name) m.handleNewBackup(event.Name) } case err, ok := <-m.watcher.errors: if !ok { return } - logger.Backup.Errorf("%s Backup watcher error: %s", Identifier, err.Error()) + logger.Backup.Errorf("%s Backup watcher error: %s", identifier, err.Error()) } } } diff --git a/src/managers/backupmgr/restore.go b/src/managers/backupmgr/restore.go index 51dfeafd..8ce94533 100644 --- a/src/managers/backupmgr/restore.go +++ b/src/managers/backupmgr/restore.go @@ -17,7 +17,7 @@ import ( func (m *BackupManager) RestoreBackup(index int) error { m.mu.Lock() defer m.mu.Unlock() - logger.Backup.Infof("Restoring backup with index %s", fmt.Sprintf("%d", index)) + logger.Backup.Infof("Restoring backup with index %d", index) groups, err := m.getBackupGroups() if err != nil { diff --git a/src/managers/backupmgr/watcher.go b/src/managers/backupmgr/watcher.go index a131c2e4..179126d4 100644 --- a/src/managers/backupmgr/watcher.go +++ b/src/managers/backupmgr/watcher.go @@ -19,16 +19,16 @@ type fsWatcher struct { } // newFsWatcher creates a new file system watcher -func newFsWatcher(path string, Identifier string) (*fsWatcher, error) { +func newFsWatcher(path string, identifier string) (*fsWatcher, error) { // Normalize path normalizedPath := filepath.Clean(path) - logger.Backup.Debugf("%s Creating watcher for path: %s ", Identifier, normalizedPath) + logger.Backup.Debugf("%s Creating watcher for path: %s", identifier, normalizedPath) watcher, err := fsnotify.NewWatcher() if err != nil { - return nil, fmt.Errorf("%s failed to create watcher: %w", Identifier, err) + return nil, fmt.Errorf("%s failed to create watcher: %w", identifier, err) } - logger.Backup.Debugf("%s Watcher created successfully", Identifier) + logger.Backup.Debugf("%s Watcher created successfully", identifier) // Watch the root save path and all subdirectories err = filepath.WalkDir(normalizedPath, func(subPath string, d os.DirEntry, err error) error { @@ -37,16 +37,16 @@ func newFsWatcher(path string, Identifier string) (*fsWatcher, error) { } if d.IsDir() { if err := watcher.Add(subPath); err != nil { - logger.Backup.Errorf("%s Failed to add subdir %s to watcher: %s ", Identifier, subPath, err.Error()) + logger.Backup.Errorf("%s Failed to add subdir %s to watcher: %s", identifier, subPath, err.Error()) } else { - logger.Backup.Debugf("%s Added subdir %s to watcher", Identifier, subPath) + logger.Backup.Debugf("%s Added subdir %s to watcher", identifier, subPath) } } return nil }) if err != nil { watcher.Close() - return nil, fmt.Errorf("%s failed to add subdirectories to watcher: %w", Identifier, err) + return nil, fmt.Errorf("%s failed to add subdirectories to watcher: %w", identifier, err) } w := &fsWatcher{ From 26ce3eca705327daf967d7e328962227dc962a27 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 26 Sep 2025 19:13:49 +0200 Subject: [PATCH 24/33] added basic validation and a hint to the world gen settings page to show a hint (not forcing) so the user knows to fill all settings. Also includes a change to update "Vulcan" worldIds to "Vulcan2" --- UIMod/onboard_bundled/assets/css/config.css | 71 +++++++++--------- .../js/{config.js => world-gen-config.js} | 74 +++++++++++++++---- UIMod/onboard_bundled/localization/en-US.json | 21 +++--- UIMod/onboard_bundled/ui/config.html | 21 +++--- src/web/TwoBoxForm.go | 2 +- src/web/configpage.go | 7 +- src/web/templatevars.go | 1 + 7 files changed, 115 insertions(+), 82 deletions(-) rename UIMod/onboard_bundled/assets/js/{config.js => world-gen-config.js} (52%) diff --git a/UIMod/onboard_bundled/assets/css/config.css b/UIMod/onboard_bundled/assets/css/config.css index d36b27a3..e42fb13a 100644 --- a/UIMod/onboard_bundled/assets/css/config.css +++ b/UIMod/onboard_bundled/assets/css/config.css @@ -4,31 +4,30 @@ /* Wizard Button */ .wizard-button-container { display: flex; -/* Tooltip styles */ -[title] { + justify-content: center; + margin-bottom: 25px; +} + +.wizard-button { + display: flex; + align-items: center; + background-color: rgba(0, 255, 171, 0.15); + border: 2px solid var(--primary); + border-radius: 12px; + padding: 12px 24px; + font-family: 'Press Start 2P', cursive; + font-size: 0.9rem; + letter-spacing: 1px; + transition: all 0.3s ease; position: relative; - cursor: help; + overflow: hidden; + z-index: 1; + box-shadow: 0 0 15px rgba(0, 255, 171, 0.3); } -[title]:hover::before { - content: attr(title); +.wizard-button::before { + content: ''; position: absolute; - bottom: 100%; - left: 50%; - transform: translateX(-50%); - padding: 8px; - background-color: rgba(0, 0, 0, 0.9); - color: var(--primary); - border-radius: 4px; - font-size: 0.85em; - white-space: pre-line; - z-index: 1000; - box-shadow: 0 0 10px rgba(0, 255, 171, 0.2); - border: 1px solid var(--primary); - pointer-events: none; - min-width: 200px; - text-align: center; -} top: 0; left: -100%; width: 100%; @@ -161,6 +160,19 @@ filter: brightness(1.2); } +.fill-hint-wraper{ + background-color: var(--danger); + border-radius: 8px; +} + +.fill-hint{ + font-size: 1rem; + color: #ffffff; + padding: 2%; + font-style: italic; + text-align: center; +} + /* Responsive adjustments */ @media (max-width: 768px) { .section-navigation { @@ -366,21 +378,4 @@ select option { .feature-list li:hover { transform: translateX(3px); background-color: rgba(0, 0, 0, 0.4); -} - -.invalid { - border-color: #ff4d4d !important; - box-shadow: 0 0 10px rgba(255, 77, 77, 0.2); -} - -.invalid:focus { - box-shadow: 0 0 15px rgba(255, 77, 77, 0.4); -} - -.valid-options { - font-size: 0.85rem; - color: var(--primary); - margin-top: 5px; - font-family: 'Share Tech Mono', monospace; - opacity: 0.8; } \ No newline at end of file diff --git a/UIMod/onboard_bundled/assets/js/config.js b/UIMod/onboard_bundled/assets/js/world-gen-config.js similarity index 52% rename from UIMod/onboard_bundled/assets/js/config.js rename to UIMod/onboard_bundled/assets/js/world-gen-config.js index 8988c314..1fd14e51 100644 --- a/UIMod/onboard_bundled/assets/js/config.js +++ b/UIMod/onboard_bundled/assets/js/world-gen-config.js @@ -16,12 +16,16 @@ const worldConfigs = { conditions: ['MimasDefault', 'MimasBrutal'], locations: ['MimasSpawnCentralMesa', 'MimasSpawnHarrietCrater', 'MimasSpawnCraterField', 'MimasSpawnDustBowl'] }, + Vulcan2: { + conditions: ['VulcanDefault', 'VulcanBrutal'], + locations: ['VulcanSpawnVestaValley', 'VulcanSpawnEtnasFury', 'VulcanSpawnIxionsDemise', 'VulcanSpawnTitusReach'] + }, Vulcan: { conditions: ['VulcanDefault', 'VulcanBrutal'], locations: ['VulcanSpawnVestaValley', 'VulcanSpawnEtnasFury', 'VulcanSpawnIxionsDemise', 'VulcanSpawnTitusReach'] }, Venus: { - conditions: ['VenusDefault', 'VulcanBrutal'], + conditions: ['VenusDefault', 'VulcanBrutal (yes, VULCAN Brutal!)'], locations: ['VenusSpawnGaiaValley', 'VenusSpawnDaisyValley', 'VenusSpawnFaithValley', 'VenusSpawnDuskValley'] } }; @@ -33,14 +37,53 @@ const worldIdInput = document.getElementById('WorldID'); const difficultyInput = document.getElementById('Difficulty'); const startConditionInput = document.getElementById('StartCondition'); const startLocationInput = document.getElementById('StartLocation'); +const fillHintWrapper = document.getElementById('fill-hint-wraper'); + +// Function to check if New Terrain tab is active +function isNewTerrainTabActive() { + const terrainButton = document.querySelector('button.section-nav-button[data-section="terrain-settings"].active'); + return !!terrainButton; +} + +// Function to check if one but not all fields are filled +function shouldShowFillHint() { + const hasDifficulty = difficultyInput.value && difficultyInput.value.trim() !== ''; + const hasStartCondition = startConditionInput.value && startConditionInput.value.trim() !== ''; + const hasStartLocation = startLocationInput.value && startLocationInput.value.trim() !== ''; + + // Don't show hint for these specific combinations + if (hasDifficulty && !hasStartCondition && !hasStartLocation) { + return false; // Only difficulty filled + } + if (hasDifficulty && hasStartCondition && !hasStartLocation) { + return false; // Difficulty and Start Condition filled + } + if (hasDifficulty && hasStartCondition && hasStartLocation) { + return false; // All fields filled + } + + // Show hint for all other combinations where at least one field is filled + const filledInputs = [hasDifficulty, hasStartCondition, hasStartLocation].filter(Boolean).length; + return filledInputs > 0; +} + +// Function to toggle fill hint visibility +function toggleFillHint() { + if (shouldShowFillHint()) { + fillHintWrapper.style.display = 'flex'; + } else { + fillHintWrapper.style.display = 'none'; + } +} // Function to validate inputs function validateInputs() { const selectedWorld = worldIdInput.value; const worldConfig = worldConfigs[selectedWorld]; + const inputs = [worldIdInput, difficultyInput, startConditionInput, startLocationInput]; // Reset all validation states - [worldIdInput, difficultyInput, startConditionInput, startLocationInput].forEach(input => { + inputs.forEach(input => { input.classList.remove('invalid'); const infoDiv = input.nextElementSibling; if (infoDiv && infoDiv.classList.contains('input-info')) { @@ -51,25 +94,25 @@ function validateInputs() { // Validate difficulty if (!validDifficulties.includes(difficultyInput.value)) { difficultyInput.classList.add('invalid'); - updateInfoText(difficultyInput, `Valid options: ${validDifficulties.join(', ')}`); + updateInfoText(difficultyInput, `${validDifficulties.join(', ')}`); } if (worldConfig) { // Validate start condition if (!worldConfig.conditions.includes(startConditionInput.value)) { startConditionInput.classList.add('invalid'); - updateInfoText(startConditionInput, `Valid options for ${selectedWorld}: ${worldConfig.conditions.join(', ')}`); + updateInfoText(startConditionInput, `${selectedWorld}: ${worldConfig.conditions.join(', ')}`); } // Validate start location if (!worldConfig.locations.includes(startLocationInput.value)) { startLocationInput.classList.add('invalid'); - updateInfoText(startLocationInput, `Valid options for ${selectedWorld}: ${worldConfig.locations.join(', ')}`); + updateInfoText(startLocationInput, `${selectedWorld}: ${worldConfig.locations.join(', ')}`); } - } else if (selectedWorld) { - worldIdInput.classList.add('invalid'); - updateInfoText(worldIdInput, `Valid worlds: ${Object.keys(worldConfigs).join(', ')}`); } + + // Toggle fill hint visibility + toggleFillHint(); } function updateInfoText(input, text) { @@ -83,10 +126,13 @@ function updateInfoText(input, text) { } // Add event listeners -worldIdInput.addEventListener('change', validateInputs); -difficultyInput.addEventListener('change', validateInputs); -startConditionInput.addEventListener('change', validateInputs); -startLocationInput.addEventListener('change', validateInputs); +worldIdInput.addEventListener('input', validateInputs); +difficultyInput.addEventListener('input', validateInputs); +startConditionInput.addEventListener('input', validateInputs); +startLocationInput.addEventListener('input', validateInputs); -// Initialize validation on page load -document.addEventListener('DOMContentLoaded', validateInputs); \ No newline at end of file +// Initialize validation and fill hint on page load +document.addEventListener('DOMContentLoaded', () => { + validateInputs(); + toggleFillHint(); +}); \ No newline at end of file diff --git a/UIMod/onboard_bundled/localization/en-US.json b/UIMod/onboard_bundled/localization/en-US.json index 8412aea5..be8029fe 100644 --- a/UIMod/onboard_bundled/localization/en-US.json +++ b/UIMod/onboard_bundled/localization/en-US.json @@ -26,7 +26,7 @@ "UIText_BasicSettings": "Basic Settings", "UIText_NetworkSettings": "Network Settings", "UIText_AdvancedSettings": "Advanced Settings", - "UIText_TerrainSettings": "New Terrain", + "UIText_TerrainSettings": "World generation", "basic": { "UIText_BasicServerSettings": "Basic Server Settings", "UIText_ServerName": "Server Name", @@ -82,21 +82,20 @@ "UIText_GameBranch": "Game Branch", "UIText_GameBranchInfo": "Branch of the game to use. When changed, requires to restart SSUI!", "UIText_AllowAutoGameServerUpdates": "Enable Auto Game Server Updates", - "UIText_AllowAutoGameServerUpdatesInfo": "Allow the gameserver to automatically query for and update to the latest version. Attention: Restarts the server when a new version was found and installed. Will send multiple warning messages to the sever with SAY commands 60-10 seconds before the restart." + "UIText_AllowAutoGameServerUpdatesInfo": "Allow the gameserver to automatically query for and update to the latest version. Attention: Restarts the server when a new version was found and installed. Will send multiple warning messages to the sever with SAY commands 60-10 seconds before the restart.", + "UIText_AutoStartServerOnStartup": "Auto Start Server on Startup", + "UIText_AutoStartServerOnStartupInfo": "Automatically start the gameserver when the SSUI is started. Defaults to false." }, "terrain": { - "UIText_TerrainSettingsHeader": "NEW TERRAIN AND SAVE SYSTEM SETTINGS", - "UIText_TerrainWarning": "These settings are only useful if you are running a Stationeers build NEWER than September 2025. Old savegames are NOT compatible with the new system, but can be migrated with JacksonTheMaster's Migration tool.. Related \"how to\" Information on the FAQ there also applies to the Dedicated Server.", - "UIText_UseNewTerrainAndSave": "Use New Terrain and Save System", - "UIText_UseNewTerrainAndSaveInfo": "Set to TRUE to enable handling of .save files in the Backup manager and argument parsing. If set to false, only Stationeers versions before the terrain rework (≈ mid 2025) will work. Defaults to TRUE!", + "UIText_TerrainSettingsHeader": "Optional world generation settings", + "UIText_TerrainWarning": "You can leave these settings blank to default to the defaults of the selected world type. Once a World is created, these settings no longer have an effect.", "UIText_Difficulty": "Difficulty", - "UIText_DifficultyInfo": "Difficulty to create the world with. Defaults to Normal if empty.", + "UIText_DifficultyInfo": "Difficulty to create the world with.", "UIText_StartCondition": "Start Condition", - "UIText_StartConditionInfo": "Start condition to create the world with. Defaults to the default start condition for the world type if empty.", + "UIText_StartConditionInfo": "Start condition to create the world with.", "UIText_StartLocation": "Start Location", - "UIText_StartLocationInfo": "Start location to create the world with. Defaults to DefaultStartLocation if empty.", - "UIText_AutoStartServerOnStartup": "Auto Start Server on Startup", - "UIText_AutoStartServerOnStartupInfo": "Automatically start the gameserver when the SSUI is started. Defaults to false." + "UIText_StartLocationInfo": "Start location to create the world with.", + "UIText_TerrainSettingsFillHint": "Please fill out the fields before the one you filled with a value, else Stationeers will have parsing issues." }, "discord": { "UIText_DiscordIntegrationTitle": "Discord Integration Benefits", diff --git a/UIMod/onboard_bundled/ui/config.html b/UIMod/onboard_bundled/ui/config.html index e300dc39..9280582a 100644 --- a/UIMod/onboard_bundled/ui/config.html +++ b/UIMod/onboard_bundled/ui/config.html @@ -54,9 +54,11 @@

{{.UIText_ServerConfig}}

+ {{if eq .IsNewTerrainAndSaveSystemTrueSelected "selected"}} + + {{end}} -
@@ -85,7 +87,6 @@

{{.UIText_BasicServerSettings}}

{{.UIText_WorldIDInfo}}
-
Valid worlds: Lunar, Mars2, Europa3, MimasHerschel, Vulcan, Venus
@@ -262,17 +263,10 @@

{{.UIText_AdvancedConfiguration}}

{{.UIText_TerrainSettingsHeader}}

{{.UIText_TerrainWarning}}
+
-
- - -
{{.UIText_UseNewTerrainAndSaveInfo}}
-
-
+
@@ -293,6 +287,9 @@

{{.UIText_TerrainSettingsHeader}}

{{.UIText_StartLocationInfo}}
+
@@ -460,7 +457,7 @@

{{.UIText_DiscordIntegrationBenefits}}

}); - + \ No newline at end of file diff --git a/src/web/TwoBoxForm.go b/src/web/TwoBoxForm.go index a3baf602..c5b88773 100644 --- a/src/web/TwoBoxForm.go +++ b/src/web/TwoBoxForm.go @@ -98,7 +98,7 @@ func ServeTwoBoxFormTemplate(w http.ResponseWriter, r *http.Request) { if config.GetIsNewTerrainAndSaveSystem() { worldOptions = []struct{ Display, Value string }{ {Display: "Lunar", Value: "Lunar"}, - {Display: "Vulcan", Value: "Vulcan"}, + {Display: "Vulcan", Value: "Vulcan2"}, {Display: "Venus", Value: "Venus"}, {Display: "Mars", Value: "Mars2"}, {Display: "Europa", Value: "Europa3"}, diff --git a/src/web/configpage.go b/src/web/configpage.go index b711a1cd..a7e77269 100644 --- a/src/web/configpage.go +++ b/src/web/configpage.go @@ -76,12 +76,9 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) { } isNewTerrainAndSaveSystemTrueSelected := "" - isNewTerrainAndSaveSystemFalseSelected := "" if config.GetIsNewTerrainAndSaveSystem() { isNewTerrainAndSaveSystemTrueSelected = "selected" - } else { - isNewTerrainAndSaveSystemFalseSelected = "selected" } autoStartServerTrueSelected := "" @@ -160,7 +157,6 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) { AutoRestartServerTimer: config.GetAutoRestartServerTimer(), IsNewTerrainAndSaveSystem: fmt.Sprintf("%v", config.GetIsNewTerrainAndSaveSystem()), IsNewTerrainAndSaveSystemTrueSelected: isNewTerrainAndSaveSystemTrueSelected, - IsNewTerrainAndSaveSystemFalseSelected: isNewTerrainAndSaveSystemFalseSelected, AutoStartServerOnStartup: fmt.Sprintf("%v", config.GetAutoStartServerOnStartup()), AutoStartServerOnStartupTrueSelected: autoStartServerTrueSelected, AutoStartServerOnStartupFalseSelected: autoStartServerFalseSelected, @@ -228,14 +224,13 @@ func ServeConfigPage(w http.ResponseWriter, r *http.Request) { UIText_GameBranchInfo: localization.GetString("UIText_GameBranchInfo"), UIText_TerrainSettingsHeader: localization.GetString("UIText_TerrainSettingsHeader"), UIText_TerrainWarning: localization.GetString("UIText_TerrainWarning"), - UIText_UseNewTerrainAndSave: localization.GetString("UIText_UseNewTerrainAndSave"), - UIText_UseNewTerrainAndSaveInfo: localization.GetString("UIText_UseNewTerrainAndSaveInfo"), UIText_Difficulty: localization.GetString("UIText_Difficulty"), UIText_DifficultyInfo: localization.GetString("UIText_DifficultyInfo"), UIText_StartCondition: localization.GetString("UIText_StartCondition"), UIText_StartConditionInfo: localization.GetString("UIText_StartConditionInfo"), UIText_StartLocation: localization.GetString("UIText_StartLocation"), UIText_StartLocationInfo: localization.GetString("UIText_StartLocationInfo"), + UIText_TerrainSettingsFillHint: localization.GetString("UIText_TerrainSettingsFillHint"), UIText_AutoStartServerOnStartup: localization.GetString("UIText_AutoStartServerOnStartup"), UIText_AutoStartServerOnStartupInfo: localization.GetString("UIText_AutoStartServerOnStartupInfo"), UIText_AllowAutoGameServerUpdates: localization.GetString("UIText_AllowAutoGameServerUpdates"), diff --git a/src/web/templatevars.go b/src/web/templatevars.go index 6a36f2f2..8c0cc2ab 100644 --- a/src/web/templatevars.go +++ b/src/web/templatevars.go @@ -148,6 +148,7 @@ type ConfigTemplateData struct { UIText_StartConditionInfo string UIText_StartLocation string UIText_StartLocationInfo string + UIText_TerrainSettingsFillHint string UIText_AutoStartServerOnStartup string UIText_AutoStartServerOnStartupInfo string UIText_AllowAutoGameServerUpdates string From ec5c7f42372aa51b9a68cfa901e691c34473a0c1 Mon Sep 17 00:00:00 2001 From: JacksonTheMaster <81807824+JacksonTheMaster@users.noreply.github.com> Date: Fri, 26 Sep 2025 19:25:59 +0200 Subject: [PATCH 25/33] Added indicators to validation Co-authored-by: mitoskalandiel --- .../assets/js/world-gen-config.js | 19 +++++++++++++------ UIMod/onboard_bundled/ui/config.html | 6 +++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/UIMod/onboard_bundled/assets/js/world-gen-config.js b/UIMod/onboard_bundled/assets/js/world-gen-config.js index 1fd14e51..1210fb7d 100644 --- a/UIMod/onboard_bundled/assets/js/world-gen-config.js +++ b/UIMod/onboard_bundled/assets/js/world-gen-config.js @@ -87,27 +87,34 @@ function validateInputs() { input.classList.remove('invalid'); const infoDiv = input.nextElementSibling; if (infoDiv && infoDiv.classList.contains('input-info')) { + // Restore original text if it exists, otherwise keep current text infoDiv.textContent = infoDiv.getAttribute('data-original-text') || infoDiv.textContent; } }); // Validate difficulty - if (!validDifficulties.includes(difficultyInput.value)) { + if (!difficultyInput.value || difficultyInput.value.trim() === '') { + updateInfoText(difficultyInput, validDifficulties.join(', ')); + } else if (!validDifficulties.includes(difficultyInput.value)) { difficultyInput.classList.add('invalid'); - updateInfoText(difficultyInput, `${validDifficulties.join(', ')}`); + updateInfoText(difficultyInput, `❌${validDifficulties.join(', ')}`); } if (worldConfig) { // Validate start condition - if (!worldConfig.conditions.includes(startConditionInput.value)) { - startConditionInput.classList.add('invalid'); + if (!startConditionInput.value || startConditionInput.value.trim() === '') { updateInfoText(startConditionInput, `${selectedWorld}: ${worldConfig.conditions.join(', ')}`); + } else if (!worldConfig.conditions.includes(startConditionInput.value)) { + startConditionInput.classList.add('invalid'); + updateInfoText(startConditionInput, `❌${selectedWorld}: ${worldConfig.conditions.join(', ')}`); } // Validate start location - if (!worldConfig.locations.includes(startLocationInput.value)) { - startLocationInput.classList.add('invalid'); + if (!startLocationInput.value || startLocationInput.value.trim() === '') { updateInfoText(startLocationInput, `${selectedWorld}: ${worldConfig.locations.join(', ')}`); + } else if (!worldConfig.locations.includes(startLocationInput.value)) { + startLocationInput.classList.add('invalid'); + updateInfoText(startLocationInput, `❌${selectedWorld}: ${worldConfig.locations.join(', ')}`); } } diff --git a/UIMod/onboard_bundled/ui/config.html b/UIMod/onboard_bundled/ui/config.html index 9280582a..b080d61c 100644 --- a/UIMod/onboard_bundled/ui/config.html +++ b/UIMod/onboard_bundled/ui/config.html @@ -270,21 +270,21 @@

{{.UIText_TerrainSettingsHeader}}

-
{{.UIText_DifficultyInfo}}
+
✅{{.UIText_DifficultyInfo}}
-
{{.UIText_StartConditionInfo}}
+
✅{{.UIText_StartConditionInfo}}
-
{{.UIText_StartLocationInfo}}
+
✅{{.UIText_StartLocationInfo}}