Initial Commit
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: GamingUniverse construction
|
||||
|
||||
The system SHALL export `GamingUniverse` accepting `startTime`, `timeScale`, `UniverseClient`, and optional `clock`.
|
||||
|
||||
#### Scenario: Construction
|
||||
|
||||
- **WHEN** `new GamingUniverse({ startTime, timeScale: 3600, universe })` is called
|
||||
- **THEN** the instance is created with `getGameTime()` returning `startTime`
|
||||
|
||||
### Requirement: Time scale control
|
||||
|
||||
The system SHALL provide `setTimeScale`, `pause`, `resume`, and `isPaused`.
|
||||
|
||||
#### Scenario: Pause and resume
|
||||
|
||||
- **WHEN** `pause()` is called
|
||||
- **THEN** `isPaused()` returns `true`
|
||||
- **AND** `getGameTime()` stops advancing
|
||||
- **AND** after `resume()`, `isPaused()` returns `false`
|
||||
|
||||
### Requirement: Set game time directly
|
||||
|
||||
The system SHALL provide `setGameTime` to override the clock to a specific date.
|
||||
|
||||
#### Scenario: Direct time set
|
||||
|
||||
- **WHEN** `setGameTime(futureDate)` is called
|
||||
- **THEN** `getGameTime()` returns `futureDate`
|
||||
|
||||
### Requirement: Scene queries at game time
|
||||
|
||||
The system SHALL delegate `getScene` to `UniverseClient.getScene` using the current game time.
|
||||
|
||||
#### Scenario: Scene query
|
||||
|
||||
- **WHEN** `getScene(observer)` is called while paused
|
||||
- **THEN** the query uses the paused game time, not real time
|
||||
|
||||
### Requirement: AsyncScheduler integration
|
||||
|
||||
The system SHALL wrap `@suaveplan/timing`'s `AsyncScheduler` to drive game time ticks.
|
||||
|
||||
#### Scenario: Scheduler usage
|
||||
|
||||
- **WHEN** `GamingUniverse` is constructed
|
||||
- **THEN** it creates or references an `AsyncScheduler` from `@suaveplan/timing`
|
||||
- **AND** `dispose()` stops the scheduler
|
||||
|
||||
### Requirement: Event emission
|
||||
|
||||
The system SHALL emit events via `@suaveplan/events` for `hourChanged`, `dayChanged`, `seasonChanged`, `sunriseStarted`, `sunsetStarted`, `moonriseStarted`, `moonsetStarted`, and `eclipseStarted`.
|
||||
|
||||
#### Scenario: Day change event
|
||||
|
||||
- **WHEN** game time advances across a midnight boundary
|
||||
- **THEN** a `dayChanged` event is emitted with the new `gameTime` and `dayNumber`
|
||||
|
||||
### Requirement: Signal cancellation
|
||||
|
||||
The system SHALL pass `AbortSignal` through to `UniverseClient.getScene` and cancel in-flight queries.
|
||||
|
||||
#### Scenario: Abort in-flight
|
||||
|
||||
- **WHEN** `getScene` is called and the signal is aborted
|
||||
- **THEN** the promise rejects with an abort error
|
||||
|
||||
### Requirement: Dispose idempotency
|
||||
|
||||
The system SHALL provide `dispose()` that stops the clock and cancels all in-flight queries, callable multiple times safely.
|
||||
|
||||
#### Scenario: Double dispose
|
||||
|
||||
- **WHEN** `dispose()` is called twice
|
||||
- **THEN** no error is thrown
|
||||
- **AND** the instance is fully shut down after the first call
|
||||
|
||||
### Requirement: UniverseClient exposure
|
||||
|
||||
The system SHALL expose the underlying `UniverseClient` via a readonly `universe` property.
|
||||
|
||||
#### Scenario: Access underlying client
|
||||
|
||||
- **WHEN** `gamingUniverse.universe` is accessed
|
||||
- **THEN** it returns the `UniverseClient` passed at construction
|
||||
Reference in New Issue
Block a user