This commit is contained in:
root
2026-09-20 14:16:41 +02:00
parent 0798933b05
commit b6d1909d7f
56 changed files with 3752 additions and 1989 deletions
+35 -10
View File
@@ -11,12 +11,12 @@ import (
"strconv"
"strings"
"wh/comms"
"wh/config"
"wh/runner"
"wh/store"
"wh/vm"
"wh/world"
"halcyon/comms"
"halcyon/config"
"halcyon/runner"
"halcyon/store"
"halcyon/vm"
"halcyon/world"
)
type Server struct {
@@ -33,7 +33,9 @@ type Server struct {
// POST /assemble assembly text -> program (base64), size
// GET /ships -> your ships
// PUT /ships/{id}/program raw bytecode (ship must be in inventory)
// POST /ships/{id}/launch (enters the belt on the next run)
// POST /ships/{id}/launch {"slot": n} (optional) (enters the belt on the next run; with a slot, that
// slot's code is assembled and sealed in first)
// GET /slots, GET/PUT/DELETE /slots/{n} the sixteen code slots (1-3 are read-only examples)
// PUT /ships/{id}/uplink raw bytes (<= comm size) (replaces any queued uplink)
// GET /ships/{id}/downlink raw bytes, X-Downlink-Day header
//
@@ -49,6 +51,10 @@ func New(st *store.Store, cfg config.Config) *http.ServeMux {
mux.Handle("GET /ships", s.auth(s.ships))
mux.Handle("PUT /ships/{id}/program", s.auth(s.program))
mux.Handle("POST /ships/{id}/launch", s.auth(s.launch))
mux.Handle("GET /slots", s.auth(s.listSlots))
mux.Handle("GET /slots/{n}", s.auth(s.getSlot))
mux.Handle("PUT /slots/{n}", s.auth(s.putSlot))
mux.Handle("DELETE /slots/{n}", s.auth(s.deleteSlot))
mux.Handle("PUT /ships/{id}/uplink", s.auth(s.uplink))
mux.Handle("GET /ships/{id}/downlink", s.auth(s.downlink))
return mux
@@ -148,9 +154,9 @@ func (s *Server) info(w http.ResponseWriter, r *http.Request) {
}
writeJSON(w, http.StatusOK, map[string]any{
"day": s.currentDay(r.Context()),
"ticks_per_day": s.cfg.TicksPerDay,
"tick_seconds": s.cfg.TickSeconds(),
"cycles_per_tick": s.cfg.CyclesPerTick,
"turns_per_day": s.cfg.TicksPerDay,
"turn_seconds": s.cfg.TickSeconds(),
"cycles_per_turn": s.cfg.CyclesPerTick,
"program_bytes": s.cfg.ProgramBytes,
"ram_bytes": s.cfg.RAMBytes,
"comm_bytes": s.cfg.CommBytes,
@@ -242,6 +248,25 @@ func (s *Server) launch(w http.ResponseWriter, r *http.Request, p store.Player)
if !ok {
return
}
// An optional {"slot": n} chooses which code slot the ship flies. Without it
// the ship launches with the program already sealed in it (PUT .../program).
body, ok := readBody(w, r, 1<<10)
if !ok {
return
}
if strings.TrimSpace(string(body)) != "" {
var req struct {
Slot *int `json:"slot"`
}
if err := json.Unmarshal(body, &req); err != nil {
httpError(w, http.StatusBadRequest, `body must be {"slot": <1-16>} or empty`)
return
}
if req.Slot != nil {
s.launchFromSlot(w, r, p, id, *req.Slot)
return
}
}
if err := s.st.Launch(r.Context(), p.ID, id); err != nil {
fail(w, err)
return