68 lines
2.2 KiB
Go
68 lines
2.2 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
)
|
|
|
|
// CodeSlot is a player's saved source code.
|
|
type CodeSlot struct {
|
|
Slot int
|
|
Name string
|
|
Source string
|
|
}
|
|
|
|
// ListCodeSlots returns the names of a player's saved slots, keyed by slot number.
|
|
func (q *Q) ListCodeSlots(ctx context.Context, owner int64) (map[int]string, error) {
|
|
rows, err := q.query(ctx, `SELECT slot, name FROM code_slots WHERE player_id = ?`, owner)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
out := map[int]string{}
|
|
for rows.Next() {
|
|
var n int
|
|
var name string
|
|
if err := rows.Scan(&n, &name); err != nil {
|
|
return nil, err
|
|
}
|
|
out[n] = name
|
|
}
|
|
return out, rows.Err()
|
|
}
|
|
|
|
// GetCodeSlot returns one saved slot, or ErrNotFound if it is empty.
|
|
func (q *Q) GetCodeSlot(ctx context.Context, owner int64, slot int) (CodeSlot, error) {
|
|
cs := CodeSlot{Slot: slot}
|
|
err := q.row(ctx, `SELECT name, source FROM code_slots WHERE player_id = ? AND slot = ?`, owner, slot).Scan(&cs.Name, &cs.Source)
|
|
if err == sql.ErrNoRows {
|
|
return cs, ErrNotFound
|
|
}
|
|
return cs, err
|
|
}
|
|
|
|
// PutCodeSlot saves source in a slot, replacing whatever was there.
|
|
func (q *Q) PutCodeSlot(ctx context.Context, owner int64, slot int, name, source, at string) error {
|
|
_, err := q.exec(ctx, `INSERT INTO code_slots (player_id, slot, name, source, updated_at) VALUES (?, ?, ?, ?, ?)
|
|
ON CONFLICT (player_id, slot) DO UPDATE SET name = excluded.name, source = excluded.source, updated_at = excluded.updated_at`,
|
|
owner, slot, name, source, at)
|
|
return err
|
|
}
|
|
|
|
// DeleteCodeSlot empties a slot. Emptying an empty slot is not an error.
|
|
func (q *Q) DeleteCodeSlot(ctx context.Context, owner int64, slot int) error {
|
|
_, err := q.exec(ctx, `DELETE FROM code_slots WHERE player_id = ? AND slot = ?`, owner, slot)
|
|
return err
|
|
}
|
|
|
|
// LaunchWithProgram seals prog into a docked ship and queues it for launch in
|
|
// one step, replacing any program it already had.
|
|
func (q *Q) LaunchWithProgram(ctx context.Context, owner, ship int64, prog []byte) error {
|
|
if _, err := q.ownedStatus(ctx, owner, ship); err != nil {
|
|
return err
|
|
}
|
|
res, err := q.exec(ctx, `UPDATE ships SET program = ?, status = ? WHERE id = ? AND owner_id = ? AND status = ?`,
|
|
prog, StatusLaunching, ship, owner, StatusInventory)
|
|
return q.requireOneRow(res, err)
|
|
}
|