package provision import ( "fmt" "os" "path/filepath" "strings" "zlh-agent/internal/state" ) /* WriteEula writes eula.txt for all Minecraft variants. */ func WriteEula(cfg state.Config) error { dir := ServerDir(cfg) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("mkdir for eula: %w", err) } content := []byte("eula=true\n") return os.WriteFile(filepath.Join(dir, "eula.txt"), content, 0644) } /* WriteServerProperties writes server.properties for jar-based Minecraft servers. Forge/NeoForge generate their own, so they are skipped. */ func WriteServerProperties(cfg state.Config) error { variant := strings.ToLower(cfg.Variant) // Forge/NeoForge auto-generate properties if variant == "forge" || variant == "neoforge" { return nil } dir := ServerDir(cfg) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("mkdir for server.properties: %w", err) } var gamePort int if len(cfg.Ports) > 0 { gamePort = cfg.Ports[0] } else { gamePort = 25565 } motd := cfg.World if motd == "" { motd = "ZeroLagHub Server" } content := fmt.Sprintf( `motd=%s server-port=%d query.port=%d allow-flight=true online-mode=false difficulty=normal max-players=20 `, motd, gamePort, gamePort+1, ) return os.WriteFile(filepath.Join(dir, "server.properties"), []byte(content), 0644) } /* WriteStartScript creates start.sh for all supported games. - Vanilla/Paper/Purpur/Fabric: exec java -jar server.jar - Forge/NeoForge: use JAVA_TOOL_OPTIONS and run.sh */ func WriteStartScript(cfg state.Config) error { dir := ServerDir(cfg) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("mkdir for start.sh: %w", err) } variant := strings.ToLower(cfg.Variant) javaBin := filepath.Join(JavaRoot, "java") // ------------------------------------------------------------ // Memory calculation // ------------------------------------------------------------ mem := cfg.MemoryMB if mem <= 0 { switch variant { case "forge", "neoforge": mem = 4096 // default Forge memory default: mem = 2048 } } xmx := mem xms := mem / 2 if xms < 512 { xms = 512 } if xms > xmx { xms = xmx } // ------------------------------------------------------------ // Build script based on variant // ------------------------------------------------------------ var script string switch variant { // ------------------------------------------------------------ // Forge-based loaders // ------------------------------------------------------------ case "forge", "neoforge": script = fmt.Sprintf( `#!/bin/bash cd %s export JAVA_TOOL_OPTIONS="-Xms%dM -Xmx%dM" if [ -f "./run.sh" ]; then exec /bin/bash ./run.sh elif [ -f "./run" ]; then exec /bin/bash ./run else echo "ERROR: Forge run script not found!" exit 1 fi `, dir, xms, xmx) // ------------------------------------------------------------ // All jar-based servers (vanilla, paper, purpur, fabric, quilt) // ------------------------------------------------------------ default: script = fmt.Sprintf( `#!/bin/bash cd %s exec %s -Xms%dM -Xmx%dM -jar server.jar nogui `, dir, javaBin, xms, xmx) } // ------------------------------------------------------------ // Write start.sh // ------------------------------------------------------------ path := filepath.Join(dir, "start.sh") if err := os.WriteFile(path, []byte(script), 0755); err != nil { return fmt.Errorf("write start.sh: %w", err) } return nil }