86 lines
2.1 KiB
Go
86 lines
2.1 KiB
Go
package minecraft
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"zlh-agent/internal/provision"
|
|
"zlh-agent/internal/state"
|
|
)
|
|
|
|
func WaitUntilReady(cfg state.Config, timeout, interval time.Duration) error {
|
|
start := time.Now()
|
|
ports := candidatePorts(cfg)
|
|
protocols := []int{ProtocolForVersion(cfg.Version), 767, 765, 763, 762, 754}
|
|
protocols = dedupeInts(protocols)
|
|
|
|
attempt := 0
|
|
deadline := start.Add(timeout)
|
|
var lastErr error
|
|
|
|
for {
|
|
attempt++
|
|
for _, port := range ports {
|
|
for _, protocol := range protocols {
|
|
if _, err := QueryStatus("127.0.0.1", port, protocol); err == nil {
|
|
elapsed := time.Since(start).Milliseconds()
|
|
log.Printf("[lifecycle] vmid=%d phase=probe result=ready attempt=%d elapsed_ms=%d port=%d protocol=%d", cfg.VMID, attempt, elapsed, port, protocol)
|
|
return nil
|
|
} else {
|
|
lastErr = err
|
|
}
|
|
}
|
|
}
|
|
|
|
elapsed := time.Since(start).Milliseconds()
|
|
log.Printf("[lifecycle] vmid=%d phase=probe result=not_ready attempt=%d elapsed_ms=%d err=%v", cfg.VMID, attempt, elapsed, lastErr)
|
|
|
|
if time.Now().After(deadline) {
|
|
if lastErr != nil {
|
|
return fmt.Errorf("minecraft readiness probe timeout after %s: %w", timeout, lastErr)
|
|
}
|
|
return fmt.Errorf("minecraft readiness probe timeout after %s", timeout)
|
|
}
|
|
time.Sleep(interval)
|
|
}
|
|
}
|
|
|
|
func candidatePorts(cfg state.Config) []int {
|
|
ports := make([]int, 0, 3)
|
|
propsPath := filepath.Join(provision.ServerDir(cfg), "server.properties")
|
|
if b, err := os.ReadFile(propsPath); err == nil {
|
|
lines := strings.Split(string(b), "\n")
|
|
for _, l := range lines {
|
|
if strings.HasPrefix(l, "server-port=") {
|
|
if p, err := strconv.Atoi(strings.TrimPrefix(l, "server-port=")); err == nil && p > 0 {
|
|
ports = append(ports, p)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if len(cfg.Ports) > 0 && cfg.Ports[0] > 0 {
|
|
ports = append(ports, cfg.Ports[0])
|
|
}
|
|
ports = append(ports, 25565)
|
|
return dedupeInts(ports)
|
|
}
|
|
|
|
func dedupeInts(in []int) []int {
|
|
seen := make(map[int]struct{}, len(in))
|
|
out := make([]int, 0, len(in))
|
|
for _, v := range in {
|
|
if _, ok := seen[v]; ok {
|
|
continue
|
|
}
|
|
seen[v] = struct{}{}
|
|
out = append(out, v)
|
|
}
|
|
return out
|
|
}
|