package main import ( "encoding/json" "fmt" "io" "os" "path/filepath" "strings" ) type VsServerConfigOptions struct { Version string `json:"Version"` ServerName string `json:"ServerName"` Port int `json:"Port"` IpAddress string `json:"IpAddress"` MaxClients int `json:"MaxClients"` Password string `json:"Password"` DefaultRole string `json:"DefaultRole"` GuestRole string `json:"GuestRole"` PreApprovedRole string `json:"PreApprovedRole"` } func PrepareInstanceConfig(templateVersion string, instanceConfigPath string, options VsServerConfigOptions, cfg *AppConfig) error { return SyncInstanceConfig(templateVersion, instanceConfigPath, options, cfg) } func SyncInstanceConfig(templateVersion string, instanceConfigPath string, options VsServerConfigOptions, cfg *AppConfig) error { templatePath := filepath.Join(cfg.Storage.ConfigTemplatesDir, templateVersion, "serverconfig.json") if _, err := os.Stat(instanceConfigPath); os.IsNotExist(err) { if err := os.MkdirAll(filepath.Dir(instanceConfigPath), 0755); err != nil { return fmt.Errorf("failed creating instance directory tree: %w", err) } source, err := os.Open(templatePath) if err != nil { return fmt.Errorf("failed opening baseline template file: %w", err) } defer source.Close() destination, err := os.Create(instanceConfigPath) if err != nil { return fmt.Errorf("failed creating target instance configuration: %w", err) } _, err = io.Copy(destination, source) destination.Close() if err != nil { return fmt.Errorf("failed cloning configuration template payload: %w", err) } } data, err := os.ReadFile(instanceConfigPath) if err != nil { return fmt.Errorf("failed reading configuration data: %w", err) } var rawConfig map[string]interface{} if err := json.Unmarshal(data, &rawConfig); err != nil { return fmt.Errorf("failed parsing configuration JSON payload: %w", err) } rawConfig["ServerName"] = options.ServerName rawConfig["Port"] = options.Port rawConfig["MaxClients"] = options.MaxClients if options.Password != "" { rawConfig["Password"] = options.Password } else { rawConfig["Password"] = nil } instanceDir := filepath.Dir(instanceConfigPath) if worldConfig, ok := rawConfig["WorldConfig"].(map[string]interface{}); ok { worldConfig["SaveFileLocation"] = filepath.Join(instanceDir, "Saves", "default.vcdbs") } if modPaths, ok := rawConfig["ModPaths"].([]interface{}); ok { for i, pathVal := range modPaths { if strPath, ok := pathVal.(string); ok && (strings.Contains(strPath, "/vs-manager/instances/") || filepath.IsAbs(strPath)) && strPath != "Mods" { modPaths[i] = filepath.Join(instanceDir, "Mods") } } } updatedData, err := json.MarshalIndent(rawConfig, "", " ") if err != nil { return fmt.Errorf("failed marshaling updated configuration adjustments: %w", err) } return os.WriteFile(instanceConfigPath, updatedData, 0644) }