5.4 KiB
Skyrama TUI
A terminal user interface for a Skyrama-clone airport management game, built with BubbleTea.
Tech Stack
- Go 1.22
- github.com/charmbracelet/bubbletea — TUI framework
- github.com/charmbracelet/lipgloss — terminal styling
- github.com/charmbracelet/bubbles — list, textinput, etc.
- github.com/go-sql-driver/mysql — MySQL driver
- golang.org/x/crypto/bcrypt — password hashing
- sqlc — SQL → Go codegen (generated files in
internal/db/)
Project Structure
cmd/skyrama/main.go # Entry point: rootModel (login → app screen transition)
internal/
db/
client.go # Thin wrapper over sqlc Queries; auth, transactions, row mappers
db.go / querier.go /
queries.sql.go / models.go # sqlc-generated files (do not edit by hand)
model/model.go # Domain types: Airport, Plane, PlayerPlane, Building, Contract, …
style/style.go # All lipgloss styles and colors
ui/
app.go # AppModel: tab bar, 10s tick, window sizing
login.go # Login / register screen
airport_view.go # Tab 0: resources, XP bar
fleet.go # Tab 1: planes, launch/land flights
buildings.go # Tab 2: owned buildings + build catalogue
contracts.go # Tab 3: active delivery contracts
shop.go # Tab 4: buy planes
sql/
schema.sql # MySQL DDL (source of truth)
queries.sql # sqlc input queries
sqlc.yaml # sqlc configuration
buidl.bat # build script (go build -o skyrama ./cmd/skyrama/)
Database
- Engine: MySQL
- Default DSN:
skyramaUser:Skyrama1234.@tcp(127.0.0.1:3306)/skyrama_clone?parseTime=true - Override via
--dsnflag orSKYRAMA_DSNenvironment variable. - Schema must be applied before first run:
sql/schema.sql
Build & Run
# Build
buidl.bat
# or
go build -o skyrama.exe ./cmd/skyrama/
# Run (uses default DSN if SKYRAMA_DSN not set)
.\skyrama.exe
# Run with custom DSN
.\skyrama.exe --dsn "user:pass@tcp(host:port)/dbname?parseTime=true"
# Regenerate sqlc files after editing sql/queries.sql
sqlc_generate.bat
Architecture
Screen flow
rootModel (main.go) owns two screens:
screenLogin→ui.LoginModel— handlesLoginSuccessMsg/LoginErrMsgscreenApp→ui.AppModel— full game TUI after login
On LoginSuccessMsg, rootModel builds AppModel and injects all sub-models (Fleet, Buildings, Contracts, Shop) with the resolved airportID.
AppModel (ui/app.go)
- Owns all tab sub-models as value/pointer fields.
- Routes
tea.Msgto the active tab sub-model. - Fires a 10-second tick that:
- Calls
RefreshResources(regenerates fuel/passengers via MySQLTIMESTAMPDIFF) - Auto-lands planes ready to land (
GetPlanesReadyToLand+LandFlight)
- Calls
db.Client (internal/db/client.go)
Wraps the sqlc *Queries object. All multi-step DB operations are wrapped in transactions:
BuyPlane— deducts cash, insertsplayer_planes, logs transactionLaunchFlight— deducts fuel, sets plane status toflying, logs transactionLandFlight— awards cash + XP, parks plane in hangar, logs transactionConstructBuilding— deducts cash, insertsairport_buildings, logs transaction
Some queries use raw database/sql (e.g. GetAirportBuildings, GetActiveContracts) because the sqlc-generated join queries are not yet wired up.
Domain model (internal/model/model.go)
Key types: Airport, Plane, PlayerPlane, Building, AirportBuilding, Contract, Country, User.
PlayerPlane.TimeRemainingSeconds() computes seconds until landing client-side.
Contract.ProgressPct() returns delivery progress as an integer percentage.
Tab index constants: TabAirport=0, TabFleet=1, TabBuildings=2, TabContracts=3, TabShop=4.
Key Bindings
| Key | Action |
|---|---|
1-5 / tab / shift+tab |
Switch tabs |
↑↓ / j k |
Navigate lists |
enter / space |
Select / action |
/ |
Filter list |
r |
Refresh current tab |
h / l |
Switch sub-tabs (Buildings) |
q / ctrl+c |
Quit |
Fleet tab: enter on idle plane → launch; enter on flying plane → check/land if ready.
Buildings tab: h/l or ←→ → toggle Owned ↔ Build catalogue; enter in catalogue → construct.
Shop tab: enter / b → buy selected plane (deducts cash, parks in first hangar).
DB Schema Overview
Core tables: users, airports, planes, player_planes, buildings, airport_buildings, countries, products, airport_contracts, airport_inventory.
Log tables: currency_transaction_logs, completed_flight_routes_log.
Stage 1 (not yet active): recipes, building_products.
Plane statuses: idle | maintenance | boarding | taxiing | flying
Building types: none | storage | support | operation | passive | shop | production
Aircraft sizes: small | medium | large | huge
Aircraft types: plane | helicopter | seaplane | spaceship
Development Stages
- Stage 0 (current): Launch planes to country's base airport, basic resources, buildings, shop.
- Stage 1: NPCs, cargo planes, shop buildings, recipes, inventory.
- Stage 2: Player progression, building upgrades, effects, complex recipes.
- Stage 3: TBD.