@dice-o-rolla/dice-engine 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/errors.d.ts CHANGED
@@ -16,3 +16,10 @@ export declare class RollLimitExceededError extends RangeError {
16
16
  readonly actual: number;
17
17
  constructor(limit: RollLimit, maximum: number, actual: number);
18
18
  }
19
+ export type TraceLimit = 'events' | 'frames' | 'samples';
20
+ export declare class TraceLimitExceededError extends RangeError {
21
+ readonly limit: TraceLimit;
22
+ readonly maximum: number;
23
+ readonly actual: number;
24
+ constructor(limit: TraceLimit, maximum: number, actual: number);
25
+ }
package/dist/errors.js CHANGED
@@ -32,3 +32,15 @@ export class RollLimitExceededError extends RangeError {
32
32
  this.actual = actual;
33
33
  }
34
34
  }
35
+ export class TraceLimitExceededError extends RangeError {
36
+ limit;
37
+ maximum;
38
+ actual;
39
+ constructor(limit, maximum, actual) {
40
+ super(`Physical roll trace exceeds ${limit} limit of ${maximum} (received ${actual})`);
41
+ this.name = 'TraceLimitExceededError';
42
+ this.limit = limit;
43
+ this.maximum = maximum;
44
+ this.actual = actual;
45
+ }
46
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { DiceEngine } from './dice-engine.js';
2
- export { DiceEngineDestroyedError, RollCancelledError, RollLimitExceededError, RollTimeoutError, } from './errors.js';
3
- export type { RollLimit } from './errors.js';
4
- export type { DiceEngineEvents, DiceEngineFacade, DiceEngineLimits, DiceEngineOptions, DiceMaterialType, DiceTheme, FrameScheduler, FrameToken, RollOptions, } from './types.js';
2
+ export { DiceEngineDestroyedError, RollCancelledError, RollLimitExceededError, RollTimeoutError, TraceLimitExceededError, } from './errors.js';
3
+ export type { RollLimit, TraceLimit } from './errors.js';
4
+ export type { DiceEngineEvents, DiceEngineFacade, DiceEngineLimits, DiceEngineOptions, DiceCollisionEvent, DiceImpactEvent, DiceCollisionEventOptions, DiceMaterialType, DiceRemovalReason, DiceRemoveEvent, DiceTheme, DiceTraceLimits, DiceVisualEvent, FrameScheduler, FrameToken, PhysicalRollFrame, PhysicalRollFrameDie, PhysicalRollTrace, PhysicalRollTraceCollisionEvent, PhysicalRollTraceDie, PhysicalRollTraceEvent, PhysicalRollTraceImpactEvent, PhysicalRollTraceProducer, PhysicalRollTraceProfile, RegisterEngineVisualPresetOptions, ReplayOptions, RollOptions, SimulateOptions, } from './types.js';
5
+ export { getStandardVisualPresetId, PHYSICAL_DIE_TYPES, STANDARD_VISUAL_PRESETS, type PhysicalDieType, } from './visual-presets.js';
6
+ export { DICE_ENGINE_VERSION } from './version.js';
package/dist/index.js CHANGED
@@ -1,2 +1,4 @@
1
1
  export { DiceEngine } from './dice-engine.js';
2
- export { DiceEngineDestroyedError, RollCancelledError, RollLimitExceededError, RollTimeoutError, } from './errors.js';
2
+ export { DiceEngineDestroyedError, RollCancelledError, RollLimitExceededError, RollTimeoutError, TraceLimitExceededError, } from './errors.js';
3
+ export { getStandardVisualPresetId, PHYSICAL_DIE_TYPES, STANDARD_VISUAL_PRESETS, } from './visual-presets.js';
4
+ export { DICE_ENGINE_VERSION } from './version.js';
package/dist/types.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- import type { DieResult, RandomSource, RollMode, RollResult, RollSession } from '@dice-o-rolla/dice-core';
1
+ import type { DieResult, DieType, QuaternionLike, RandomSource, RollMode, RollResult, RollSession, Vector3Like } from '@dice-o-rolla/dice-core';
2
2
  import type { DicePhysicsMaterial, PhysicsWorld, SettlingOptions, ThrowGeneratorOptions, TrayOptions } from '@dice-o-rolla/dice-physics';
3
3
  import type { DiceRenderer, RendererTheme, RendererViewport } from '@dice-o-rolla/dice-renderer';
4
+ import type { RegisterVisualPresetOptions, VisualPresetDescriptor } from '@dice-o-rolla/dice-renderer';
5
+ import type { PhysicalDieType } from './visual-presets.js';
4
6
  export interface FrameToken {
5
7
  cancel(): void;
6
8
  }
@@ -13,18 +15,129 @@ export interface RollOptions {
13
15
  readonly mode?: RollMode;
14
16
  readonly signal?: AbortSignal;
15
17
  }
18
+ export interface SimulateOptions {
19
+ readonly seed: number;
20
+ readonly captureFrames?: boolean;
21
+ /** Capture one frame every N fixed simulation steps. */
22
+ readonly frameIntervalSteps?: number;
23
+ }
24
+ export interface ReplayOptions {
25
+ readonly theme?: Partial<DiceTheme>;
26
+ readonly signal?: AbortSignal;
27
+ }
28
+ export interface PhysicalRollFrameDie {
29
+ readonly id: string;
30
+ readonly position: Vector3Like;
31
+ readonly quaternion: QuaternionLike;
32
+ }
33
+ export interface PhysicalRollFrame {
34
+ readonly elapsedSeconds: number;
35
+ readonly dice: readonly PhysicalRollFrameDie[];
36
+ }
37
+ export interface PhysicalRollTraceDie {
38
+ readonly id: string;
39
+ readonly type: DieType;
40
+ readonly presetId: string;
41
+ readonly geometryId: string;
42
+ readonly definitionFingerprint: string;
43
+ readonly scale: number;
44
+ readonly faceLabels?: Readonly<Record<number, string | number>>;
45
+ readonly initial: {
46
+ readonly position: Vector3Like;
47
+ readonly quaternion: QuaternionLike;
48
+ readonly impulse: Vector3Like;
49
+ readonly torqueImpulse: Vector3Like;
50
+ };
51
+ }
52
+ export interface PhysicalRollTraceCollisionEvent {
53
+ readonly kind: 'collision';
54
+ readonly elapsedSeconds: number;
55
+ readonly dieId: string;
56
+ readonly otherDieId?: string;
57
+ readonly started: boolean;
58
+ }
59
+ export interface PhysicalRollTraceImpactEvent {
60
+ readonly kind: 'impact';
61
+ readonly elapsedSeconds: number;
62
+ readonly dieId: string;
63
+ readonly otherDieId?: string;
64
+ readonly force: number;
65
+ }
66
+ export type PhysicalRollTraceEvent = PhysicalRollTraceCollisionEvent | PhysicalRollTraceImpactEvent;
67
+ export interface PhysicalRollTraceProfile {
68
+ readonly fixedStepSeconds: number;
69
+ readonly settling: SettlingOptions;
70
+ readonly throw: ThrowGeneratorOptions;
71
+ readonly tray: TrayOptions;
72
+ readonly diceMaterial: DicePhysicsMaterial;
73
+ }
74
+ export interface PhysicalRollTraceProducer {
75
+ readonly name: '@dice-o-rolla/dice-engine';
76
+ readonly version: string;
77
+ }
78
+ /** JSON-serializable, renderer-neutral output of a deterministic physical simulation. */
79
+ export interface PhysicalRollTrace {
80
+ readonly version: 1;
81
+ readonly producer: PhysicalRollTraceProducer;
82
+ readonly notation: string;
83
+ readonly seed: number;
84
+ readonly fixedStepSeconds: number;
85
+ readonly frameIntervalSteps: number;
86
+ readonly durationSeconds: number;
87
+ readonly profile: PhysicalRollTraceProfile;
88
+ readonly dice: readonly PhysicalRollTraceDie[];
89
+ readonly frames: readonly PhysicalRollFrame[];
90
+ readonly events: readonly PhysicalRollTraceEvent[];
91
+ readonly result: RollResult;
92
+ }
93
+ export interface DiceTraceLimits {
94
+ readonly maxFrames: number;
95
+ readonly maxSamples: number;
96
+ readonly maxEvents: number;
97
+ }
98
+ export interface RegisterEngineVisualPresetOptions extends RegisterVisualPresetOptions {
99
+ readonly makeDefault?: boolean;
100
+ }
16
101
  export interface DiceEngineLimits {
17
102
  readonly maxNotationLength: number;
18
103
  readonly maxLogicalDice: number;
19
104
  readonly maxPhysicalDice: number;
20
105
  readonly maxQueuedRolls: number;
21
106
  }
107
+ export interface DiceVisualEvent {
108
+ readonly sessionId: string;
109
+ readonly dieId: string;
110
+ readonly dieType: string;
111
+ readonly presetId: string;
112
+ readonly skinId?: string;
113
+ readonly soundPackId?: string;
114
+ }
115
+ export type DiceRemovalReason = 'replaced' | 'cancelled' | 'failed' | 'cleared' | 'destroyed';
116
+ export interface DiceRemoveEvent extends DiceVisualEvent {
117
+ readonly reason: DiceRemovalReason;
118
+ }
119
+ export interface DiceCollisionEvent extends DiceVisualEvent {
120
+ readonly otherDieId?: string;
121
+ readonly started: boolean;
122
+ }
123
+ export interface DiceImpactEvent extends DiceVisualEvent {
124
+ readonly otherDieId?: string;
125
+ readonly force: number;
126
+ }
127
+ export interface DiceCollisionEventOptions {
128
+ readonly enabled: boolean;
129
+ readonly maxEventsPerFrame: number;
130
+ }
22
131
  export interface DiceEngineEvents {
23
132
  readonly 'roll:start': RollSession;
133
+ readonly 'die:spawn': DiceVisualEvent;
24
134
  readonly 'die:settled': {
25
135
  readonly sessionId: string;
26
136
  readonly die: DieResult;
27
137
  };
138
+ readonly 'die:remove': DiceRemoveEvent;
139
+ readonly 'die:collision': DiceCollisionEvent;
140
+ readonly 'die:impact': DiceImpactEvent;
28
141
  readonly 'roll:complete': RollResult;
29
142
  readonly 'roll:cancel': RollSession;
30
143
  readonly 'theme:change': DiceTheme;
@@ -47,13 +160,23 @@ export interface DiceEngineOptions {
47
160
  readonly diceMaterial?: DicePhysicsMaterial;
48
161
  readonly theme?: Partial<DiceTheme>;
49
162
  readonly limits?: Partial<DiceEngineLimits>;
163
+ readonly traceLimits?: Partial<DiceTraceLimits>;
164
+ readonly visualPresets?: readonly VisualPresetDescriptor[];
165
+ readonly visualPresetIds?: Partial<Readonly<Record<PhysicalDieType, string>>>;
166
+ readonly collisionEvents?: Partial<DiceCollisionEventOptions>;
50
167
  }
51
168
  export interface DiceEngineFacade {
52
169
  initialize(): Promise<void>;
53
170
  roll(notation: string, options?: RollOptions): Promise<RollResult>;
171
+ simulate(notation: string, options: SimulateOptions): Promise<PhysicalRollTrace>;
172
+ replay(trace: PhysicalRollTrace, options?: ReplayOptions): Promise<void>;
54
173
  cancel(sessionId?: string): boolean;
55
174
  clear(): void;
56
175
  resize(viewport: RendererViewport): void;
57
176
  setTheme(theme: Partial<DiceTheme>): DiceTheme;
177
+ registerVisualPreset(preset: VisualPresetDescriptor, options?: RegisterEngineVisualPresetOptions): VisualPresetDescriptor;
178
+ unregisterVisualPreset(id: string): boolean;
179
+ setVisualPreset(dieType: PhysicalDieType, presetId: string): void;
180
+ getVisualPreset(dieType: PhysicalDieType): VisualPresetDescriptor;
58
181
  destroy(): void;
59
182
  }
@@ -0,0 +1,2 @@
1
+ /** Runtime package version used in portable trace provenance. */
2
+ export declare const DICE_ENGINE_VERSION = "0.3.0";
@@ -0,0 +1,2 @@
1
+ /** Runtime package version used in portable trace provenance. */
2
+ export const DICE_ENGINE_VERSION = '0.3.0';
@@ -0,0 +1,7 @@
1
+ import type { DieType } from '@dice-o-rolla/dice-core';
2
+ import type { VisualPresetDescriptor } from '@dice-o-rolla/dice-renderer';
3
+ export type PhysicalDieType = Exclude<DieType, 'd100'>;
4
+ export declare const PHYSICAL_DIE_TYPES: readonly PhysicalDieType[];
5
+ export declare const STANDARD_VISUAL_PRESETS: readonly VisualPresetDescriptor[];
6
+ export declare function getStandardVisualPresetId(dieType: PhysicalDieType): string;
7
+ export declare function isPhysicalDieType(value: unknown): value is PhysicalDieType;
@@ -0,0 +1,20 @@
1
+ export const PHYSICAL_DIE_TYPES = Object.freeze([
2
+ 'd4',
3
+ 'd6',
4
+ 'd8',
5
+ 'd10',
6
+ 'd12',
7
+ 'd20',
8
+ ]);
9
+ export const STANDARD_VISUAL_PRESETS = Object.freeze(PHYSICAL_DIE_TYPES.map((dieType) => Object.freeze({
10
+ id: `standard:${dieType}`,
11
+ dieType,
12
+ geometryId: dieType,
13
+ scale: 1,
14
+ })));
15
+ export function getStandardVisualPresetId(dieType) {
16
+ return `standard:${dieType}`;
17
+ }
18
+ export function isPhysicalDieType(value) {
19
+ return PHYSICAL_DIE_TYPES.some((type) => type === value);
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dice-o-rolla/dice-engine",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "Framework-neutral physical dice engine with Rapier and Three.js browser adapters.",
5
5
  "keywords": [
6
6
  "dice",
@@ -47,12 +47,12 @@
47
47
  "registry": "https://registry.npmjs.org/"
48
48
  },
49
49
  "dependencies": {
50
- "@dice-o-rolla/dice-core": "0.1.1",
51
- "@dice-o-rolla/dice-geometry": "0.1.1",
52
- "@dice-o-rolla/dice-physics": "0.1.1",
53
- "@dice-o-rolla/dice-physics-rapier": "0.1.1",
54
- "@dice-o-rolla/dice-renderer": "0.1.1",
55
- "@dice-o-rolla/dice-renderer-three": "0.1.1"
50
+ "@dice-o-rolla/dice-core": "0.3.0",
51
+ "@dice-o-rolla/dice-geometry": "0.3.0",
52
+ "@dice-o-rolla/dice-physics": "0.3.0",
53
+ "@dice-o-rolla/dice-physics-rapier": "0.3.0",
54
+ "@dice-o-rolla/dice-renderer": "0.3.0",
55
+ "@dice-o-rolla/dice-renderer-three": "0.3.0"
56
56
  },
57
57
  "engines": {
58
58
  "node": ">=20.0.0"