Documentation
¶
Index ¶
- Constants
- Variables
- func CatalogHash() (string, error)
- func LoadAllWithWarnings() ([]System, []LoadWarning, error)
- type Atmosphere
- type CelestialBody
- func (cb *CelestialBody) GravitationalParameter() float64
- func (cb *CelestialBody) MassKg() float64
- func (cb *CelestialBody) RadiusMeters() float64
- func (cb *CelestialBody) SemimajorAxisMeters() float64
- func (cb *CelestialBody) SideralOrbitSeconds() float64
- func (cb *CelestialBody) SideralRotationSeconds() float64
- func (cb CelestialBody) SurfaceColorHex() string
- type LatLonPair
- type LoadWarning
- type Mass
- type Moon
- type OrbitalElement
- type Planet
- type ScaleClass
- type System
- type Texture
- type TextureBand
- type TextureEllipse
- type TextureMask
- type TextureRegion
- type TextureStar
Constants ¶
const ( // G is the universal gravitational constant in m^3 kg^-1 s^-2. G = 6.67430e-11 // AU is one astronomical unit in meters. AU = 1.495978707e11 // SecondsPerDay is exactly 86400. SecondsPerDay = 86400.0 // EarthMassKg is the Earth's mass in kilograms. EarthMassKg = 5.9722e24 // SunMassKg is the Sun's mass in kilograms. SunMassKg = 1.98892e30 )
Physical constants (SI).
Variables ¶
var J2000 = time.Date(2000, 1, 1, 12, 0, 0, 0, time.UTC)
J2000 is the J2000.0 epoch: January 1, 2000 12:00 TT (UTC-approximate).
Functions ¶
func CatalogHash ¶ added in v0.4.0
CatalogHash returns a sha256 hex of the canonical JSON encoding of every loaded system, sorted by name (Sol first). Stamped into save files so a load can reject saves built against a stale universe — e.g. after a v0.5 systems-JSON edit adds Luna and rewrites Body indices, the old save's body references no longer line up.
Hash is over re-marshalled structs, not raw file bytes, so cosmetic JSON whitespace edits don't churn the hash. Only semantic catalog changes (new bodies, mass / element edits) bump it.
The body Texture spec (ADR 0024) is cosmetic, not semantic, so it is zeroed in a hash-specific view before hashing — adding or editing a texture must never reject an existing save. `json:"-"` can't be used on the field itself because that would also block *loading* it; the exclusion lives here, at the hash boundary.
func LoadAllWithWarnings ¶ added in v0.7.0
func LoadAllWithWarnings() ([]System, []LoadWarning, error)
LoadAllWithWarnings is the warning-aware variant of LoadAll. The returned warnings slice contains LoadWarning entries for any user overlay files that failed to parse; embedded-catalog parse failures surface as a hard error (returned as the err value) since the embedded set must always load.
Types ¶
type Atmosphere ¶ added in v0.8.4
type Atmosphere struct {
ScaleHeight float64 `json:"scaleHeight"` // m
SurfaceDensity float64 `json:"surfaceDensity"` // kg/m³ at altitude 0
CutoffAltitude float64 `json:"cutoffAltitude"` // m above surface — drag = 0 above
Color string `json:"color,omitempty"`
}
Atmosphere is an exponential-density atmospheric model: ρ(h) = SurfaceDensity · exp(-h/ScaleHeight) for altitudes below CutoffAltitude, zero above. Color is the haze tint used by the renderer; defaults to body Color when empty.
type CelestialBody ¶
type CelestialBody struct {
ID string `json:"id"`
Name string `json:"name"`
EnglishName string `json:"englishName"`
BodyType string `json:"bodyType"`
IsPlanet bool `json:"isPlanet"`
Moons []Moon `json:"moons,omitempty"`
SemimajorAxis float64 `json:"semimajorAxis"`
Perihelion float64 `json:"perihelion,omitempty"`
Aphelion float64 `json:"aphelion,omitempty"`
Eccentricity float64 `json:"eccentricity"`
Inclination float64 `json:"inclination"`
Mass Mass `json:"mass"`
Density float64 `json:"density,omitempty"`
Gravity float64 `json:"gravity,omitempty"`
Escape float64 `json:"escape,omitempty"`
MeanRadius float64 `json:"meanRadius"`
SideralOrbit float64 `json:"sideralOrbit,omitempty"`
SideralRotation float64 `json:"sideralRotation,omitempty"`
AroundPlanet *Planet `json:"aroundPlanet,omitempty"`
DiscoveredBy string `json:"discoveredBy,omitempty"`
DiscoveryDate string `json:"discoveryDate,omitempty"`
// Stellar-only properties
Temperature float64 `json:"temperature,omitempty"`
StellarClass string `json:"stellarClass,omitempty"`
Age float64 `json:"age,omitempty"`
// Optional precise Keplerian elements (overrides semimajor/eccentricity/etc.)
OrbitalElements *OrbitalElement `json:"orbitalElements,omitempty"`
// Longitude of ascending node (Ω) and argument of periapsis (ω),
// in degrees. Zero when unknown — flat-plane approximation.
LongitudeOfAscendingNode float64 `json:"longitudeOfAscendingNode,omitempty"`
ArgumentOfPeriapsis float64 `json:"argumentOfPeriapsis,omitempty"`
// ParentID identifies this body's gravitational parent. Empty
// means "system primary" (e.g. the Sun for Sol bodies). Set on
// moons (e.g. Luna.ParentID = "earth"). Drives hierarchical
// BodyPosition recursion and FindPrimary's nested-SOI walk.
// v0.5.0+.
ParentID string `json:"parentId,omitempty"`
// Color is the rendered display color as a hex string (e.g.
// "#5BB3FF"). When set, render.ColorFor prefers this over the
// hardcoded bodyPalette table; when empty, the table fallback +
// stellar-tint / bodyType-default chain still applies. v0.7.1+.
Color string `json:"color,omitempty"`
// SurfaceColor is the horizon-fill colour used by ViewLaunch
// (the chase-cam scene below the horizon curve). Hex string;
// empty falls back to Color via SurfaceColorHex. v0.11.0+.
SurfaceColor string `json:"surfaceColor,omitempty"`
// Atmosphere, when non-nil, declares an exponential-density
// atmosphere for this body — drives drag (v0.8.4) and haze
// rendering. Bodies without atmospheres leave this nil.
Atmosphere *Atmosphere `json:"atmosphere,omitempty"`
// TidallyLocked, when true, ties this body's rotation to its
// orbital period — the same face always points at the parent.
// SideralRotation is ignored for these bodies; the renderer
// derives sub-observer longitude from orbital phase. v0.8.5+.
TidallyLocked bool `json:"tidallyLocked,omitempty"`
// AxialTilt is the body's obliquity (rotation-axis angle from
// the orbital-plane normal), in degrees. Drives view-aware
// texture projection (v0.8.5.7+) — ViewTop on a tilted body
// reveals polar regions; Uranus's 97° tilt makes it roll
// pole-on along its orbit.
AxialTilt float64 `json:"axialTilt,omitempty"`
// AxialAzimuth is the body's spin-axis azimuth in the world
// inertial frame, in degrees. The axis projects onto the world
// X-Y plane at this angle measured counterclockwise from world
// +X (so 0° tips toward +X, 90° toward +Y, 180° toward -X).
// Combined with AxialTilt the unit spin axis is
//
// n = (sin(tilt)·cos(azimuth), sin(tilt)·sin(azimuth), cos(tilt))
//
// Defaults to 0 — same as the v0.8.5.7 launch behaviour where
// every body's axis lay in the X-Z plane. Real bodies have
// varied pole directions; populating this field lets each one
// tip the right way once we have data.
AxialAzimuth float64 `json:"axialAzimuth,omitempty"`
// Texture is the optional data-driven surface-texture spec
// (ADR 0024). nil renders a flat solid disk; the generic render
// engine consumes a non-nil block. Cosmetic, not semantic —
// deliberately excluded from CatalogHash (see catalog.go).
Texture *Texture `json:"texture,omitempty"`
}
CelestialBody describes a star, planet, or moon by its physical and orbital properties. Units: km for lengths, days for periods, degrees for angles, kg (via Mass.Value * 10^Exponent) for mass.
func LookupByID ¶ added in v0.4.0
func LookupByID(systems []System, id string) (CelestialBody, bool)
LookupByID searches every system for a body with the given ID and returns it by value. Used by the save/load layer to rehydrate the craft's primary across system boundaries — v0.1 craft is locked to Sol, but the save schema doesn't bake that assumption in.
func (*CelestialBody) GravitationalParameter ¶
func (cb *CelestialBody) GravitationalParameter() float64
GravitationalParameter returns GM in m^3/s^2.
func (*CelestialBody) MassKg ¶
func (cb *CelestialBody) MassKg() float64
MassKg returns the body's mass in kilograms.
func (*CelestialBody) RadiusMeters ¶
func (cb *CelestialBody) RadiusMeters() float64
RadiusMeters converts the stored mean radius (km) to meters.
func (*CelestialBody) SemimajorAxisMeters ¶
func (cb *CelestialBody) SemimajorAxisMeters() float64
SemimajorAxisMeters converts the stored semimajor axis (km) to meters.
func (*CelestialBody) SideralOrbitSeconds ¶ added in v0.8.5
func (cb *CelestialBody) SideralOrbitSeconds() float64
SideralOrbitSeconds converts the stored sidereal orbital period (days) to seconds. Returns 0 when no orbital period is known.
func (*CelestialBody) SideralRotationSeconds ¶ added in v0.8.5
func (cb *CelestialBody) SideralRotationSeconds() float64
SideralRotationSeconds converts the stored sidereal rotation period (hours, signed for prograde / retrograde) to seconds. Returns 0 when no rotation period is known.
func (CelestialBody) SurfaceColorHex ¶ added in v0.11.0
func (cb CelestialBody) SurfaceColorHex() string
SurfaceColorHex returns the body's launch-view horizon-fill colour, falling back to Color when SurfaceColor is unset.
type LatLonPair ¶ added in v0.20.0
LatLonPair is a single (lat, lon) vertex in degrees.
type LoadWarning ¶ added in v0.7.0
LoadWarning is returned by LoadAllWithWarnings for user-supplied overlay files that failed to parse. Embedded systems must always load — a parse failure there is a hard error, not a warning.
func (LoadWarning) Error ¶ added in v0.7.0
func (w LoadWarning) Error() string
type OrbitalElement ¶
type OrbitalElement struct {
SemimajorAxis float64 `json:"semimajorAxis"`
Eccentricity float64 `json:"eccentricity"`
Inclination float64 `json:"inclination"`
ArgumentOfPeriapsis float64 `json:"argumentOfPeriapsis"`
LongitudeOfAscendingNode float64 `json:"longitudeOfAscendingNode"`
MeanAnomaly float64 `json:"meanAnomaly"`
Epoch time.Time `json:"epoch"`
}
type ScaleClass ¶ added in v0.16.0
type ScaleClass string
ScaleClass is a coarse size/difficulty tag shared by a System and a Loadout (ADR 0014). It is purely a classification surfaced as the spawn form's craft hint — the integrator derives all dynamics from a Body's mass and radius, so a System needs no ScaleClass to work and craft are never filtered by it: any Loadout can fly in any System.
const ( // ScaleReal is the Sol-scale tag: Earth-class bodies, ~9.4 km/s to // orbit. The zero value / default — every System and Loadout that // does not set one normalizes to real via Scale(). ScaleReal ScaleClass = "real" // ScaleStrippedBack is the Lumen-scale tag: ~1/10-linear bodies with // Earth-like surface gravity, ~3.4 km/s to orbit, modelled on the // Kerbal Space Program stock system. ScaleStrippedBack ScaleClass = "stripped-back" )
func (ScaleClass) Normalize ¶ added in v0.16.0
func (c ScaleClass) Normalize() ScaleClass
Normalize maps the empty/unset value to ScaleReal and returns any other value unchanged, so callers can compare scale classes without special- casing the zero value. Unknown non-empty strings pass through verbatim (forward-compatible with overlay-supplied tags).
type System ¶
type System struct {
Name string `json:"systemName"`
Description string `json:"description"`
Distance string `json:"distance"`
Galaxy string `json:"galaxy"`
Bodies []CelestialBody `json:"bodies"`
// ScaleClass is the System's spawn-form scale hint (ADR 0014).
// Optional in JSON: an absent/empty value normalizes to ScaleReal
// via Scale(), so the pre-Lumen catalog stays real untouched. Lumen
// sets "stripped-back". Never used for filtering.
ScaleClass ScaleClass `json:"scaleClass,omitempty"`
// Source is a runtime annotation: "embedded" for the built-in
// catalog, "user" for files loaded from
// $XDG_CONFIG_HOME/terminal-space-program/systems/*.json (v0.7.0+).
// Excluded from JSON marshaling so CatalogHash is stable across
// identical-data overlays.
Source string `json:"-"`
}
System is a named collection of celestial bodies orbiting a common primary. The first body (index 0) is treated as the primary (star or barycenter).
func LoadAll ¶
LoadAll reads every embedded system JSON, merges any user overlay files from $XDG_CONFIG_HOME/terminal-space-program/systems/*.json (or ~/.config/... if XDG is unset), and returns the merged set sorted by name with Sol always first. Warnings from malformed user files are dropped — call LoadAllWithWarnings to inspect them.
func (*System) FindBody ¶
func (s *System) FindBody(query string) *CelestialBody
FindBody returns a pointer to the body with matching id or englishName. Case-insensitive on englishName; exact match on id.
func (*System) ParentOf ¶ added in v0.5.0
func (s *System) ParentOf(b CelestialBody) *CelestialBody
ParentOf returns the gravitational parent of body `b` in this system. For top-level bodies (ParentID empty) the system primary (index 0) is returned. Returns nil if b's ParentID is set but unresolvable, which signals a malformed system.
func (*System) Primary ¶
func (s *System) Primary() *CelestialBody
Primary returns the body treated as the gravitational primary (index 0).
func (*System) Scale ¶ added in v0.16.0
func (s *System) Scale() ScaleClass
Scale returns the System's normalized ScaleClass (empty => real). Systems loaded from JSON without a scaleClass field — the entire pre-Lumen catalog — report real.
type Texture ¶ added in v0.20.0
type Texture struct {
// Base is the disk's underlying surface color (hex, e.g. "#6E5F50").
// Empty falls back to the body's Color.
Base string `json:"base,omitempty"`
// Bands are latitude sweeps for gas/ice giants — ordered, first
// match wins per pixel.
Bands []TextureBand `json:"bands,omitempty"`
// Continents are filled ellipse features (maria, albedo regions,
// land masses). Layered in table order — last match wins.
Continents []TextureEllipse `json:"continents,omitempty"`
// Craters are ellipse features with optional rim + rayed ejecta —
// rendered on top of continents/bands. Last match wins.
Craters []TextureEllipse `json:"craters,omitempty"`
// Spots are storm/feature ellipses (e.g. a Great Red Spot)
// layered over bands. Last match wins.
Spots []TextureEllipse `json:"spots,omitempty"`
// Mask is the Earth-class polygon land/ocean/biome mask kind.
// Carried from PR1; rendered starting PR3.
Mask *TextureMask `json:"mask,omitempty"`
// LimbTint is an atmospheric-halo color painted over the outer
// ring of the disk (hex). Carried from PR1; rendered starting PR3.
LimbTint string `json:"limbTint,omitempty"`
// Star is the self-luminous star-surface kind (limb darkening +
// granulation, light-source exempt). Carried from PR1; rendered
// starting PR3.
Star *TextureStar `json:"star,omitempty"`
}
Texture is the optional data-driven surface-texture spec for a body (ADR 0024). It replaces the hardcoded per-body Go shaders in internal/render: a single generic engine consumes this block, so any system — including user overlays in $XDG_CONFIG_HOME — can be textured, which the old `switch b.ID` model structurally could not.
The spec carries *typed* feature kinds rather than one flat list, so each kind can render kind-specific detail. The presence of a kind selects the look; an empty block (or a body with no Texture at all) renders as a flat base-color disk.
PR1 (this slice) renders the ellipse kinds (continents / craters / spots) and bands. The mask / limb-tint / star kinds are carried in the schema from PR1 — so the field round-trips through JSON and is covered by the catalog-hash exclusion (see catalog.go) — but are consumed by the engine starting in PR3 (ADR 0024 rollout).
Texture is excluded from bodies.CatalogHash: it is cosmetic, not semantic, so it must never bump the hash and reject existing saves.
func (*Texture) Validate ¶ added in v0.20.0
Validate reports the first structural problem in a texture spec, or nil when it is renderable. It is intentionally lenient: an empty block is valid (flat disk), and absent colors fall back at render time. It flags only the cases that would otherwise render as silent garbage — malformed hex colors, non-positive ellipse radii, and inverted band ranges. Used by the loader to fail-soft on user-overlay systems (warn + drop the texture → flat disk) rather than hard-error.
type TextureBand ¶ added in v0.20.0
type TextureBand struct {
LatMin float64 `json:"latMin"`
LatMax float64 `json:"latMax"`
Color string `json:"color"`
}
TextureBand is a latitude sweep: every pixel whose body-latitude is in [LatMin, LatMax) takes Color.
type TextureEllipse ¶ added in v0.20.0
type TextureEllipse struct {
Lat float64 `json:"lat"`
Lon float64 `json:"lon"`
LatR float64 `json:"latR"`
LonR float64 `json:"lonR"`
Color string `json:"color,omitempty"`
Rim string `json:"rim,omitempty"`
Rays bool `json:"rays,omitempty"`
}
TextureEllipse is a lat/lon-axis-aligned ellipse feature. Lat/Lon is the center (degrees); LatR/LonR are the semi-axes along latitude and longitude (degrees). Color fills the ellipse. For craters, Rim (when set) colors the outer ring and Rays marks bright ejecta.
type TextureMask ¶ added in v0.20.0
type TextureMask struct {
Polys []TextureRegion `json:"polys,omitempty"`
Biomes map[string]string `json:"biomes,omitempty"`
}
TextureMask is the Earth-class polygon land/ocean mask kind. Polys is a list of named regions (land / desert / ice) given as polygon vertex lists; Biomes maps a region kind to a hex color. Carried in the schema from PR1; the engine consumes it starting PR3.
type TextureRegion ¶ added in v0.20.0
type TextureRegion struct {
Kind string `json:"kind,omitempty"`
Vertices []LatLonPair `json:"vertices,omitempty"`
}
TextureRegion is one named polygon in a TextureMask.
type TextureStar ¶ added in v0.20.0
type TextureStar struct {
Core string `json:"core,omitempty"`
Surface string `json:"surface,omitempty"`
Limb string `json:"limb,omitempty"`
Spot string `json:"spot,omitempty"`
Granulation float64 `json:"granulation,omitempty"`
Seed int64 `json:"seed,omitempty"`
}
TextureStar is the self-luminous star-surface kind: concentric limb darkening (bright Core → Surface → darker Limb) with optional granulation jitter and sunspots. A body carrying a Star block is exempt from day/night shading — it is the light source. Core / Surface / Limb are hex colors; empty ones derive from the body's Color. Granulation is the surface mottling amplitude (0..1); Seed makes the (deterministic) granulation pattern reproducible. Spot is the sunspot color; spot *positions* are taken from the texture's Spots ellipses.