Game Types and Constants Reference
This page is a reference for key types, commands, configuration constants, and AuthService methods used in the game application.
Player and Lane IDs
Source: libs/game/config/src/lib/types.ts
| Type | Values |
|---|---|
PlayerId | 'player', 'npc-1', 'npc-2', 'npc-3' |
LaneId | Same as PlayerId — each player owns one lane |
PhaseKind | 'preparation', 'combat', 'game-over' |
Match Commands
Source: libs/game/core/src/lib/api/types.ts
Send commands via dispatch(state, command).
| Command type | Required fields | When to use |
|---|---|---|
set-move-target | playerId, point | Move the player avatar |
request-plot-action | playerId, action | Queue a plot action (build, upgrade, sell…) |
clear-plot-action | playerId | Cancel all queued actions |
move-plot-action | playerId, actionId, direction | Reorder the action queue |
remove-plot-action | playerId, actionId | Remove one queued action |
purchase-send-package | playerId, plotId, targetPlayerIds | Send enemies to other players |
set-preparation-ready | playerId, ready | Mark player as ready to start combat |
build-tower-at | playerId, towerFamilyId, position | NPC direct build (bypasses plot queue) |
build-send-structure-at | playerId, position | NPC direct send structure build |
Plot Action Kinds
Source: libs/game/core/src/lib/api/types.ts (PlotActionRequest)
| Kind | Description |
|---|---|
build-tower | Place a new tower family on an empty tower plot |
branch-tower | Unlock a variant for an existing tower |
upgrade-tower-stat | Upgrade one stat (damage, attackSpeed, range, splashRadius, projectileSpeed, income) |
relocate-tower | Move a tower to a new position |
sell-tower | Sell tower for sellRefundRate of total cost |
build-send-structure | Place a send structure on a send plot |
upgrade-send-stat | Upgrade enemy health, armor, or speed |
MatchSnapshot Shape
getSnapshot(state) returns a MatchSnapshot every frame.
MatchSnapshot
├── seed, debug, nowMs
├── phase: { kind, round, remainingMs, readyPlayerIds }
├── alivePlayerIds, aliveNpcIds
├── players: Record<PlayerId, PlayerSnapshot>
│ ├── gold, coreHealth, alive, kills
│ ├── passiveIncomePerRound
│ ├── sendUpgrades: { health, armor, speed }
│ └── builderQueue: BuilderQueueItemSnapshot[]
└── lanes: Record<LaneId, LaneSnapshot>
├── plots: PlotSnapshot[] ← structures live here
├── enemies: EnemySnapshot[]
├── projectiles: ProjectileSnapshot[]
└── avatar: AvatarSnapshot
CreateSoloMatchOptions
Passed to createSoloMatch(options):
| Field | Type | Required | Notes |
|---|---|---|---|
playerDeckId | DeckId | ✅ | ID of the deck the player selected |
seed | number | ❌ | RNG seed, auto-generated if omitted |
debug | boolean | ❌ | Enables debug overlay and extra logging |
startingRound | number | ❌ | Skip to a specific round (requires debug=true) |
Balance Constants (SOLO_MATCH_CONFIG.balance)
Source: libs/game/config/src/lib/match-config.ts
| Constant | Value | Notes |
|---|---|---|
startingGold | 400 | Gold at match start |
coreHealth | 200 | HP of the player's core |
prepPhaseMs | 20 000 | Max prep phase duration |
buildChannelMs | 1 500 | Channel time for placing a tower |
branchUpgradeChannelMs | 2 000 | Channel time for branching a variant |
statUpgradeChannelMs | 1 000 | Channel time for stat upgrades |
sellRefundRate | 0.75 | Fraction of total cost returned on sell |
relocateBaseCost | 100 | Minimum gold cost for relocation |
waveHealthScale | 1.15 | Enemy HP multiplier per round |
waveSpeedScale | 1.02 | Enemy speed multiplier per round |
Grid Constants
Source: libs/game/config/src/lib/grid.ts
| Constant | Value | Notes |
|---|---|---|
SOLO_GRID_CELL_SIZE | 50 | World-space pixels per grid cell |
Buildings occupy a 2×2 footprint (100×100 world units).
Camera Constants (SOLO_MATCH_CONFIG.camera)
| Field | Value | Notes |
|---|---|---|
defaultZoom | 1 | Starting zoom level |
minZoom | 0.85 | Minimum zoom out |
maxZoom | 1.2 | Maximum zoom in |
edgePanSpeed | 0.72 | World units per ms during edge pan |
AuthService Public API
Source: apps/game/src/app/auth/auth.service.ts
| Method | Returns | Notes |
|---|---|---|
checkSession(forceFresh?) | Promise<void> | Pass true to bypass cookie cache |
clearSession() | void | Resets isLoggedIn and user to empty state |
login(email, password) | Promise<{ data, error }> | Updates isLoggedIn and user signals |
register(name, nickname, email, password) | Promise<{ data, error }> | Sends verification email on success |
logout() | Promise<void> | Clears signals |
forgotPassword(email) | Promise<{ data, error }> | Sends password reset email |
resetPassword(newPassword, token?) | Promise<{ data, error }> | Completes reset from email link |
requestProfileChange(name, nickname) | Promise<{ data, error }> | Starts confirmed profile change |
requestEmailChange(newEmail) | Promise<{ data, error }> | Starts two-step email change |
requestPasswordChange(currentPassword, newPassword) | Promise<{ data, error }> | Starts confirmed password change |
confirmAccountChange(token) | Promise<{ data, error }> | Applies any pending change |
These two methods exist in AuthService but call Better Auth endpoints that the API blocks:
changeEmail(newEmail, callbackURL?)— calls/api/auth/change-email→ blocked, returnsCONFIRMATION_REQUIREDchangePassword(newPassword, currentPassword)— calls/api/auth/change-password→ blocked, returnsCONFIRMATION_REQUIRED
Do not use them. Use requestEmailChange and requestPasswordChange instead.
Signals:
| Signal | Type | Notes |
|---|---|---|
isLoggedIn | Signal<boolean> | true when a session exists |
user | Signal<User | null> | Authenticated user data |
User Interface
interface User {
id: string;
email: string;
name: string;
nickname: string;
emailVerified: boolean;
}