Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions cmd/asobi/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ Usage:
asobi logout Clear stored credentials
asobi whoami Show current credential info
asobi init [dir] Scaffold a starter Lua game
asobi init [dir] --template <engine>
Scaffold a runnable demo (defold|godot|unity)
asobi init [dir] --template <name>
Scaffold a runnable project:
defold|godot|unity (client demo) or backend (server only)
asobi dev [--port N] [--dir <lua>]
Run a local backend for your Lua game (Docker)
asobi games List your tenant's games
Expand Down Expand Up @@ -688,7 +689,7 @@ func cmdInit() {
if engine != "" {
t, ok := template.Get(engine)
if !ok {
fatal("unknown template %q; available: %s", engine, strings.Join(template.Engines(), ", "))
fatal("unknown template %q; available: %s", engine, strings.Join(template.Names(), ", "))
}
fmt.Printf("Fetching the %s template into %s ...\n", t.Name, dir)
created, err := template.Fetch(engine, dir)
Expand All @@ -705,7 +706,12 @@ func cmdInit() {
if dir != "." {
step("cd " + dir)
}
step("Open README.md - it walks through starting the backend and opening the project in " + t.Name + ".")
if engine == "backend" {
step("docker compose up -d (asobi_lua image + Postgres on :8084)")
step("Open README.md - it covers the managed (asobi deploy) vs local (compose) paths and adding modes in lua/config.lua.")
} else {
step("Open README.md - it walks through starting the backend and opening the project in " + t.Name + ".")
}
return
}

Expand Down
37 changes: 35 additions & 2 deletions internal/scaffold/scaffold.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,19 @@ The game logic lives in ` + "`lua/match.lua`" + `. The engine loads it as the
` + "`handle_input`, `tick` and `get_state`. `match_size`" + ` sets how many players
are needed to start a match.

## Deploy
## Run it locally

Run these from this directory.
No account, no keys - runs the asobi_lua image + Postgres in Docker:

` + "```bash" + `
asobi dev
` + "```" + `

Edit ` + "`lua/`" + ` and it hot-reloads. API + WebSocket on http://localhost:8084.

## Deploy to Asobi Cloud

Managed hosting - this needs a login:

` + "```bash" + `
asobi login
Expand All @@ -74,6 +84,29 @@ asobi create <env> # e.g. asobi create prod
asobi deploy <env> lua
` + "```" + `

## Multiple game modes

To run more than the ` + "`default`" + ` mode, add a ` + "`lua/config.lua`" + ` manifest
mapping mode names to files:

` + "```lua" + `
return {
default = "match.lua",
ranked = "ranked.lua"
}
` + "```" + `

Clients pick a mode with ` + "`matchmaker.add {mode = \"ranked\"}`" + `.

## A full backend example

Want the whole picture - Docker Compose, the mode manifest, all the
` + "`ASOBI_*`" + ` env vars in one runnable repo?

` + "```bash" + `
asobi init mybackend --template backend
` + "```" + `

## Connect a client

Defold quickstart: https://github.com/widgrensit/asobi-defold
Expand Down
5 changes: 5 additions & 0 deletions internal/scaffold/scaffold_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ func TestInitCreatesWorkingGame(t *testing.T) {
t.Fatalf("README.md missing deploy step %q", step)
}
}
for _, hint := range []string{"asobi dev", "config.lua", "--template backend"} {
if !strings.Contains(string(readme), hint) {
t.Fatalf("README.md missing %q", hint)
}
}
}

func TestInitRefusesToOverwrite(t *testing.T) {
Expand Down
23 changes: 13 additions & 10 deletions internal/template/template.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Package template scaffolds a runnable client+backend game project by fetching
// one of the asobi demo repositories at a pinned commit. The demos are the single
// source of truth (no parallel templates to drift); each carries its own README
// documenting how to run the backend and open the project in its engine.
// Package template scaffolds a runnable game project by fetching one of the asobi
// demo repositories at a pinned commit: an engine template (client + backend) or
// the backend template (server-Lua backend only). The repos are the single source
// of truth (no parallel templates to drift); each carries its own README
// documenting how to run the backend and, for engine templates, open the project.
package template

import (
Expand All @@ -27,18 +28,20 @@ type Template struct {
}

var registry = map[string]Template{
"defold": {Repo: "asobi-defold-demo", Ref: "v0.2.0", Name: "Defold"},
"godot": {Repo: "asobi-godot-demo", Ref: "v0.2.0", Name: "Godot"},
"unity": {Repo: "asobi-unity-demo", Ref: "v0.2.0", Name: "Unity"},
"defold": {Repo: "asobi-defold-demo", Ref: "v0.2.0", Name: "Defold"},
"godot": {Repo: "asobi-godot-demo", Ref: "v0.2.0", Name: "Godot"},
"unity": {Repo: "asobi-unity-demo", Ref: "v0.2.0", Name: "Unity"},
"backend": {Repo: "sdk_demo_backend", Ref: "v0.1.0", Name: "Backend"},
}

const (
maxFiles = 20000
maxBytes = 500 << 20 // 500 MiB, generous for a Unity demo
)

// Engines returns the known template engine keys, sorted.
func Engines() []string {
// Names returns the known template names, sorted (e.g. defold, godot, unity,
// backend).
func Names() []string {
keys := make([]string, 0, len(registry))
for k := range registry {
keys = append(keys, k)
Expand All @@ -58,7 +61,7 @@ func Get(engine string) (Template, bool) {
func Fetch(engine, dir string) ([]string, error) {
t, ok := registry[engine]
if !ok {
return nil, fmt.Errorf("unknown template %q; available: %s", engine, strings.Join(Engines(), ", "))
return nil, fmt.Errorf("unknown template %q; available: %s", engine, strings.Join(Names(), ", "))
}
if err := requireEmptyDir(dir); err != nil {
return nil, err
Expand Down
8 changes: 4 additions & 4 deletions internal/template/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ func makeTarGz(t *testing.T, entries []entry) []byte {
return buf.Bytes()
}

func TestEnginesKnown(t *testing.T) {
got := Engines()
want := []string{"defold", "godot", "unity"}
func TestNamesKnown(t *testing.T) {
got := Names()
want := []string{"backend", "defold", "godot", "unity"}
if !reflect.DeepEqual(got, want) {
t.Fatalf("Engines() = %v, want %v", got, want)
t.Fatalf("Names() = %v, want %v", got, want)
}
for _, e := range want {
if _, ok := Get(e); !ok {
Expand Down