121 lines
3.6 KiB
Go
121 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
companion "browser.local/plugins/scum-server-plugin/companion"
|
|
)
|
|
|
|
func main() {
|
|
log.SetFlags(log.Ldate | log.Ltime | log.LUTC)
|
|
config, err := loadConfig()
|
|
if err != nil {
|
|
log.Printf("SCUM companion configuration failed: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
client, err := companion.NewClient(config, companion.Options{})
|
|
if err != nil {
|
|
log.Printf("SCUM companion client failed: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
|
defer stop()
|
|
trajectoryStatus := &companion.TrajectoryCollectionStatus{}
|
|
collector, cleanup := buildTrajectoryCollector(config, trajectoryStatus)
|
|
defer cleanup()
|
|
|
|
registry := companion.NewHandlerRegistry(defaultHandlerAvailability(config), companion.RuntimeAdapter{
|
|
BoundServerID: config.Component.ServerInstanceID,
|
|
DiagnosticsState: map[string]string{
|
|
"trajectory": trajectoryDiagnostic(config, collector),
|
|
"coordinates": "raw-world",
|
|
},
|
|
})
|
|
runtime := companion.Runtime{
|
|
Client: client,
|
|
Dispatcher: companion.Dispatcher{
|
|
Client: client,
|
|
Registry: registry,
|
|
PollLimit: 10,
|
|
Backoff: 2 * time.Second,
|
|
},
|
|
HeartbeatEvery: time.Duration(config.Timing.HeartbeatIntervalSeconds) * time.Second,
|
|
PollEvery: time.Duration(config.Timing.CommandPollIntervalSeconds) * time.Second,
|
|
Backoff: 2 * time.Second,
|
|
Health: trajectoryStatus.HealthReport,
|
|
}
|
|
|
|
errorsCh := make(chan error, 2)
|
|
go func() { errorsCh <- runtime.Run(ctx) }()
|
|
if collector != nil {
|
|
go func() { errorsCh <- collector.Run(ctx, trajectoryStatus) }()
|
|
}
|
|
|
|
err = <-errorsCh
|
|
stop()
|
|
if err != nil && !errors.Is(err, context.Canceled) {
|
|
log.Printf("SCUM companion stopped: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func loadConfig() (companion.Config, error) {
|
|
file, err := os.Open("config.yaml")
|
|
if err != nil {
|
|
return companion.Config{}, err
|
|
}
|
|
defer file.Close()
|
|
return companion.LoadConfig(file)
|
|
}
|
|
|
|
func buildTrajectoryCollector(config companion.Config, status *companion.TrajectoryCollectionStatus) (*companion.TrajectoryCollector, func()) {
|
|
cleanup := func() {}
|
|
if !config.Trajectory.Enabled {
|
|
status.Record(companion.TrajectoryCollectionReport{Status: "healthy", Reason: "trajectory collection disabled"}, nil)
|
|
return nil, cleanup
|
|
}
|
|
source, err := companion.OpenSCUMSQLiteSourceFromEnv(config.Trajectory.FileEnv)
|
|
if err != nil {
|
|
status.Record(companion.TrajectoryCollectionReport{Status: "degraded", Reason: "trajectory source unavailable"}, err)
|
|
return nil, cleanup
|
|
}
|
|
store, err := companion.OpenSCUMSQLStoreFromEnv(companion.PlatformMySQLDSNEnvironment)
|
|
if err != nil {
|
|
_ = source.Close()
|
|
status.Record(companion.TrajectoryCollectionReport{Status: "degraded", Reason: "trajectory store unavailable"}, err)
|
|
return nil, cleanup
|
|
}
|
|
cleanup = func() {
|
|
_ = source.Close()
|
|
_ = store.Close()
|
|
}
|
|
return companion.NewTrajectoryCollector(config, source, store), cleanup
|
|
}
|
|
|
|
func defaultHandlerAvailability(config companion.Config) companion.HandlerAvailability {
|
|
capabilities := map[string]bool{"companion.diagnostics": true}
|
|
for _, capability := range config.Capabilities {
|
|
if capability == "handler.vehicle.spawn" {
|
|
capabilities["vehicle.spawn"] = true
|
|
}
|
|
}
|
|
return companion.HandlerAvailability{BoundServerID: config.Component.ServerInstanceID, Approved: true, Capabilities: capabilities}
|
|
}
|
|
|
|
func trajectoryDiagnostic(config companion.Config, collector *companion.TrajectoryCollector) string {
|
|
if !config.Trajectory.Enabled {
|
|
return "disabled"
|
|
}
|
|
if collector == nil {
|
|
return "waiting"
|
|
}
|
|
return "enabled"
|
|
}
|