ci-platforms / darwin amd64 smoke (push) Skipped
ci-platforms / darwin arm64 smoke (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
ci / checks (push) Successful in 10m24s
ci / build (amd64, linux, ubuntu-24.04) (push) Successful in 12m13s
ci / release (push) Successful in 8m57s
modules/update links aego/update (net/http, TLS, x509, archives) only off js; the web build gets a browser backend with the same section, settings and aego/update API, where Check and Apply fail and State stays idle. A test compares both builds' registrations. depcheck: wasm-runtime and wasm-try variants, update in wasmDenied, wasmDeniedStd (net/http, crypto/tls, crypto/x509, archive/*) with the wasm-reaches-std rule. wasmsize -prev: playground-size and try-size print the change since their last run. Loaders show the compressed download size: wasmGzip in an export's files.json, aego-*-gzip and data-wasm-gzip on the site; docstool writes the .wasm.gz copies. Demo game.wasm 33.9 -> 26.0 MB, gzip 8.07 -> 6.25 MB.
143 lines
2.9 KiB
Go
143 lines
2.9 KiB
Go
//go:build !js
|
|
|
|
package update
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
|
|
"aego/engine/module"
|
|
upd "aego/update"
|
|
)
|
|
|
|
func newBackend() backend {
|
|
return &native{}
|
|
}
|
|
|
|
// native updates the game's own install from its release server.
|
|
type native struct {
|
|
rel *upd.Release
|
|
file string
|
|
in upd.Install
|
|
}
|
|
|
|
func (n *native) init(m *Module, ctx *module.InitContext) error {
|
|
descs := Settings()
|
|
var err error
|
|
if m.mode, err = ctx.Setting(descs[0]); err != nil {
|
|
return err
|
|
}
|
|
if m.ch, err = ctx.Setting(descs[1]); err != nil {
|
|
return err
|
|
}
|
|
if exe, err := os.Executable(); err == nil {
|
|
n.in = upd.DetectGame(exe)
|
|
}
|
|
upd.Clean(downloads(m), m.ver)
|
|
if policy(m) != upd.Off {
|
|
n.check(m)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func policy(m *Module) upd.Mode {
|
|
if m.st == nil || m.mode == 0 {
|
|
return upd.Auto
|
|
}
|
|
return upd.ParseMode(m.st.ChoiceName(m.mode))
|
|
}
|
|
|
|
func channel(m *Module) upd.Channel {
|
|
if m.st == nil || m.ch == 0 {
|
|
return upd.Stable
|
|
}
|
|
return upd.ParseChannel(m.st.ChoiceName(m.ch))
|
|
}
|
|
|
|
// downloads is where the game's updates are fetched to: UserCacheDir/<game>/updates.
|
|
func downloads(m *Module) string {
|
|
dir, _ := os.UserCacheDir()
|
|
return filepath.Join(dir, m.game, "updates")
|
|
}
|
|
|
|
func (n *native) check(m *Module) error {
|
|
m.mu.Lock()
|
|
if !m.Configured() || m.phase == Checking || m.phase == Downloading {
|
|
m.mu.Unlock()
|
|
return nil
|
|
}
|
|
m.phase, m.err = Checking, ""
|
|
src := &upd.Source{BaseURL: m.sec.URL, Channel: channel(m), Key: m.sec.PublicKey}
|
|
m.mu.Unlock()
|
|
go func() {
|
|
r, err := src.Check(context.Background())
|
|
m.mu.Lock()
|
|
switch {
|
|
case err != nil:
|
|
m.phase, m.err = Failed, err.Error()
|
|
case !r.Newer(upd.Build{Version: m.ver}):
|
|
m.phase = UpToDate
|
|
default:
|
|
m.phase, n.rel, m.newVer, m.notes = Available, r, r.Version, r.Notes
|
|
}
|
|
auto := m.phase == Available && policy(m) == upd.Auto
|
|
m.mu.Unlock()
|
|
if auto {
|
|
n.download(m)
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
func (n *native) download(m *Module) {
|
|
m.mu.Lock()
|
|
r := n.rel
|
|
if r == nil || m.phase == Downloading {
|
|
m.mu.Unlock()
|
|
return
|
|
}
|
|
m.phase = Downloading
|
|
m.mu.Unlock()
|
|
go func() {
|
|
kind := upd.KindTarball
|
|
if n.in.Kind == upd.KindAppImage || n.in.Kind == upd.KindApp {
|
|
kind = n.in.Kind
|
|
}
|
|
var file string
|
|
a, err := r.Asset(runtime.GOOS, runtime.GOARCH, kind)
|
|
if err == nil {
|
|
file, err = upd.Download(context.Background(), nil, a, filepath.Join(downloads(m), r.Version), nil)
|
|
}
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
if err != nil {
|
|
m.phase, m.err = Failed, err.Error()
|
|
return
|
|
}
|
|
m.phase, n.file = Ready, file
|
|
}()
|
|
}
|
|
|
|
func (n *native) apply(m *Module) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
if m.phase != Ready || n.rel == nil {
|
|
return errors.New("no update is downloaded")
|
|
}
|
|
if _, err := n.in.Apply(n.file, n.rel.Version); err != nil {
|
|
return err
|
|
}
|
|
cmd := exec.Command(n.in.Launch, os.Args[1:]...)
|
|
if err := cmd.Start(); err != nil {
|
|
return err
|
|
}
|
|
if m.eng != nil {
|
|
m.eng.Quit()
|
|
}
|
|
return nil
|
|
}
|