@sagl/server 0.0.0-stage → 0.1.0-next.49

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.
Files changed (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -2
  3. package/dist/actions.d.ts +46 -0
  4. package/dist/actions.js +80 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/animations.d.ts +32 -0
  7. package/dist/animations.js +95 -0
  8. package/dist/animations.js.map +1 -0
  9. package/dist/audio.d.ts +180 -0
  10. package/dist/audio.js +353 -0
  11. package/dist/audio.js.map +1 -0
  12. package/dist/audio_effects.d.ts +219 -0
  13. package/dist/audio_effects.js +84 -0
  14. package/dist/audio_effects.js.map +1 -0
  15. package/dist/camera.d.ts +188 -0
  16. package/dist/camera.js +247 -0
  17. package/dist/camera.js.map +1 -0
  18. package/dist/claims.d.ts +27 -0
  19. package/dist/claims.js +48 -0
  20. package/dist/claims.js.map +1 -0
  21. package/dist/commands.d.ts +135 -0
  22. package/dist/commands.js +373 -0
  23. package/dist/commands.js.map +1 -0
  24. package/dist/console.d.ts +21 -0
  25. package/dist/console.js +100 -0
  26. package/dist/console.js.map +1 -0
  27. package/dist/constants.d.ts +654 -0
  28. package/dist/constants.js +657 -0
  29. package/dist/constants.js.map +1 -0
  30. package/dist/cutscene.d.ts +47 -0
  31. package/dist/cutscene.js +190 -0
  32. package/dist/cutscene.js.map +1 -0
  33. package/dist/draw.d.ts +106 -0
  34. package/dist/draw.js +132 -0
  35. package/dist/draw.js.map +1 -0
  36. package/dist/effects.d.ts +91 -0
  37. package/dist/effects.js +116 -0
  38. package/dist/effects.js.map +1 -0
  39. package/dist/gangzones.d.ts +47 -0
  40. package/dist/gangzones.js +122 -0
  41. package/dist/gangzones.js.map +1 -0
  42. package/dist/geo.d.ts +11 -0
  43. package/dist/geo.js +25 -0
  44. package/dist/geo.js.map +1 -0
  45. package/dist/hud.d.ts +159 -0
  46. package/dist/hud.js +247 -0
  47. package/dist/hud.js.map +1 -0
  48. package/dist/index.d.ts +40 -0
  49. package/dist/index.js +43 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/interaction.d.ts +81 -0
  52. package/dist/interaction.js +143 -0
  53. package/dist/interaction.js.map +1 -0
  54. package/dist/junctions.d.ts +1 -0
  55. package/dist/junctions.js +330 -0
  56. package/dist/junctions.js.map +1 -0
  57. package/dist/map.d.ts +55 -0
  58. package/dist/map.js +71 -0
  59. package/dist/map.js.map +1 -0
  60. package/dist/menu.d.ts +96 -0
  61. package/dist/menu.js +129 -0
  62. package/dist/menu.js.map +1 -0
  63. package/dist/mission.d.ts +482 -0
  64. package/dist/mission.js +1258 -0
  65. package/dist/mission.js.map +1 -0
  66. package/dist/models.d.ts +56 -0
  67. package/dist/models.js +71 -0
  68. package/dist/models.js.map +1 -0
  69. package/dist/modshop.d.ts +229 -0
  70. package/dist/modshop.js +904 -0
  71. package/dist/modshop.js.map +1 -0
  72. package/dist/modshop_data.d.ts +44 -0
  73. package/dist/modshop_data.js +287 -0
  74. package/dist/modshop_data.js.map +1 -0
  75. package/dist/native.d.ts +809 -0
  76. package/dist/native.js +27 -0
  77. package/dist/native.js.map +1 -0
  78. package/dist/objects.d.ts +249 -0
  79. package/dist/objects.js +455 -0
  80. package/dist/objects.js.map +1 -0
  81. package/dist/paint.d.ts +124 -0
  82. package/dist/paint.js +84 -0
  83. package/dist/paint.js.map +1 -0
  84. package/dist/paynspray.d.ts +44 -0
  85. package/dist/paynspray.js +177 -0
  86. package/dist/paynspray.js.map +1 -0
  87. package/dist/ped.d.ts +335 -0
  88. package/dist/ped.js +536 -0
  89. package/dist/ped.js.map +1 -0
  90. package/dist/player.d.ts +685 -0
  91. package/dist/player.js +1163 -0
  92. package/dist/player.js.map +1 -0
  93. package/dist/screeneffects.d.ts +99 -0
  94. package/dist/screeneffects.js +257 -0
  95. package/dist/screeneffects.js.map +1 -0
  96. package/dist/scripts.d.ts +69 -0
  97. package/dist/scripts.js +125 -0
  98. package/dist/scripts.js.map +1 -0
  99. package/dist/server.d.ts +713 -0
  100. package/dist/server.js +1080 -0
  101. package/dist/server.js.map +1 -0
  102. package/dist/shopblips.d.ts +9 -0
  103. package/dist/shopblips.js +30 -0
  104. package/dist/shopblips.js.map +1 -0
  105. package/dist/special.d.ts +33 -0
  106. package/dist/special.js +26 -0
  107. package/dist/special.js.map +1 -0
  108. package/dist/splash.d.ts +42 -0
  109. package/dist/splash.js +55 -0
  110. package/dist/splash.js.map +1 -0
  111. package/dist/text.d.ts +19 -0
  112. package/dist/text.js +25 -0
  113. package/dist/text.js.map +1 -0
  114. package/dist/ui.d.ts +141 -0
  115. package/dist/ui.js +243 -0
  116. package/dist/ui.js.map +1 -0
  117. package/dist/vehicle.d.ts +306 -0
  118. package/dist/vehicle.js +612 -0
  119. package/dist/vehicle.js.map +1 -0
  120. package/dist/vehiclecolors.d.ts +26 -0
  121. package/dist/vehiclecolors.js +49 -0
  122. package/dist/vehiclecolors.js.map +1 -0
  123. package/dist/world.d.ts +222 -0
  124. package/dist/world.js +227 -0
  125. package/dist/world.js.map +1 -0
  126. package/dist/zone.d.ts +89 -0
  127. package/dist/zone.js +140 -0
  128. package/dist/zone.js.map +1 -0
  129. package/package.json +33 -4
@@ -0,0 +1,188 @@
1
+ import type { NativeServer } from "./native.js";
2
+ import type { Vector3 } from "./player.js";
3
+ type ThingRef = number | {
4
+ id: number;
5
+ };
6
+ /** A player, ped or vehicle the camera follows, with an offset from its middle. */
7
+ export type CameraThing = {
8
+ player: ThingRef;
9
+ offset?: Vector3;
10
+ } | {
11
+ ped: ThingRef;
12
+ offset?: Vector3;
13
+ } | {
14
+ vehicle: ThingRef;
15
+ offset?: Vector3;
16
+ };
17
+ /** What a camera looks at: a spot, or a player, ped or vehicle it follows (with an offset). */
18
+ export type CameraTarget = Vector3 | CameraThing;
19
+ /** Where a camera is: a spot, or riding along with a player, ped or vehicle (`relative`: the offset turns with it). */
20
+ export type CameraPosition = Vector3 | (CameraThing & {
21
+ relative?: boolean;
22
+ });
23
+ /**
24
+ * Depth of field's focus: metres from the camera, a spot or a player, ped
25
+ * or vehicle (with an offset) kept in focus, `"auto"` (the middle of the
26
+ * screen), or `null` (off).
27
+ */
28
+ export type CameraFocus = number | CameraTarget | "auto" | null;
29
+ /** Angles, in degrees: pan from north, anticlockwise (as headings); tilt up from level. */
30
+ export interface CameraRotation {
31
+ pan: number;
32
+ tilt?: number;
33
+ }
34
+ /** How a move speeds up and slows down. `true` is `"inOut"`, `false` `"linear"`. */
35
+ export type CameraEase = "linear" | "in" | "out" | "inOut" | boolean;
36
+ export interface CameraShot {
37
+ /** Where the camera is. */
38
+ position: CameraPosition;
39
+ /** What it looks at. Leave out (with no `rotation`) to keep looking the way it was. */
40
+ lookAt?: CameraTarget;
41
+ /** Instead of `lookAt`: pan and tilt. Ridden along `relative`, pan is from the thing's heading. */
42
+ rotation?: CameraRotation;
43
+ /** Degrees, clockwise. Left out: as it was. */
44
+ roll?: number;
45
+ /** Field of view, 5 to 120 degrees (the game's is 70). Left out: as it was. */
46
+ fov?: number;
47
+ /**
48
+ * Depth of field: sharp at this many metres from the camera, at a spot,
49
+ * on a player, ped or vehicle (with an offset; kept in focus as it and
50
+ * the camera move), or `"auto"` (whatever's in the middle of the screen);
51
+ * `null` turns it off. Left out: as it was.
52
+ */
53
+ focus?: CameraFocus;
54
+ /** How shallow the focus is, as a lens's f-number: lower blurs more. Default 4. */
55
+ aperture?: number;
56
+ /** Glides here from where the camera is over this long (ms). Default 0: a cut. */
57
+ ms?: number;
58
+ /** Default `"inOut"`. */
59
+ ease?: CameraEase;
60
+ /**
61
+ * Cinematic: black bars top and bottom, and every HUD put away (the
62
+ * game's, the chat, name tags, scripts' HUDs) until `reset()`. On `set`
63
+ * and `play`'s options.
64
+ */
65
+ widescreen?: boolean;
66
+ }
67
+ /** A point on a path: a spot, with per-point angles, roll and field of view if wanted. */
68
+ export type CameraPathPoint = Vector3 & {
69
+ pan?: number;
70
+ tilt?: number;
71
+ roll?: number;
72
+ fov?: number;
73
+ };
74
+ export interface CameraPath {
75
+ /** The points it flies through (2 to 256 in a sequence). It starts at the first: a cut there. */
76
+ path: CameraPathPoint[];
77
+ /** How long the whole path takes (ms). Or `speed`. */
78
+ ms?: number;
79
+ /** Metres a second, when `ms` isn't given. Default 10. Either way it moves evenly along the curve. */
80
+ speed?: number;
81
+ /** 0: straight lines between points; 1 (default): a smooth curve through every point. */
82
+ smoothing?: number;
83
+ /**
84
+ * What it looks at: `"ahead"` (where it's heading), a spot, a thing it
85
+ * follows, or `rotation`'s angles. Left out: the points' own pan and tilt
86
+ * if they have them, else `"ahead"`.
87
+ */
88
+ lookAt?: CameraTarget | "ahead";
89
+ /** Fixed angles all along, instead of `lookAt`. */
90
+ rotation?: CameraRotation;
91
+ /** `"ahead"`: how far along the path it looks (m). Default 5. */
92
+ lookAhead?: number;
93
+ /** Degrees all along (or the points' own `roll`, if they have them). */
94
+ roll?: number;
95
+ /** Rolls into turns like an aircraft. */
96
+ bank?: boolean;
97
+ /** All along (or the points' own `fov`, if they have them). */
98
+ fov?: number;
99
+ /**
100
+ * Depth of field: sharp at this many metres from the camera, at a spot,
101
+ * on a player, ped or vehicle (with an offset; kept in focus as it and
102
+ * the camera move), or `"auto"` (whatever's in the middle of the screen);
103
+ * `null` turns it off. Left out: as it was.
104
+ */
105
+ focus?: CameraFocus;
106
+ /** How shallow the focus is, as a lens's f-number: lower blurs more. Default 4. */
107
+ aperture?: number;
108
+ /** Speeding up from the start and slowing at the end. Default `"inOut"`. */
109
+ ease?: CameraEase;
110
+ }
111
+ /** A step of a camera sequence: a shot, a hold (stays, ms), or a path. */
112
+ export type CameraStep = CameraShot | {
113
+ hold: number;
114
+ } | CameraPath;
115
+ export interface CameraPlayOptions {
116
+ /** From the first step again after the last, until stopped. */
117
+ loop?: boolean;
118
+ /** Black bars and the HUD away, as `CameraShot.widescreen`. */
119
+ widescreen?: boolean;
120
+ }
121
+ /** A sequence playing on a player's camera (`player.camera.play`). */
122
+ export interface CameraSequence {
123
+ /** Resolves true when the last step finishes, false if stopped, replaced or handed back first. */
124
+ readonly done: Promise<boolean>;
125
+ /** Calls `fn` as each step starts (its index), as their game plays it. Returns a remover. */
126
+ onStep(fn: (step: number) => void): () => void;
127
+ /** Stops it: the camera stays where it is (`reset()` hands it back). */
128
+ stop(): void;
129
+ }
130
+ /** @internal Floats a step. */
131
+ export declare const STEP_FLOATS = 32;
132
+ /** @internal Floats a path point. */
133
+ export declare const POINT_FLOATS = 8;
134
+ /** @internal Steps as floats, for the player's game. */
135
+ export declare function encodeCamera(steps: readonly CameraStep[]): {
136
+ steps: number[];
137
+ points: number[];
138
+ };
139
+ /**
140
+ * A player's camera (`player.camera`): shots and glides between them,
141
+ * sequences of moves and paths played on their game, a freecam they fly, or
142
+ * behind them as normal. Position, what it looks at (or pan and tilt),
143
+ * roll and field of view. Client scripts have the same: `sagl.camera`.
144
+ *
145
+ * ```ts
146
+ * await player.camera.set({ position: { x: 1500, y: -1700, z: 60 }, lookAt: { x: 1480, y: -1750, z: 13 } });
147
+ * await player.camera.set({ position: { x: 1450, y: -1700, z: 40 }, lookAt: car, fov: 40, roll: 5, ms: 5000 });
148
+ * await player.camera.play([
149
+ * { path: [a, b, c, d], ms: 10000, bank: true },
150
+ * { hold: 2000 },
151
+ * ]).done;
152
+ * player.camera.reset();
153
+ * ```
154
+ */
155
+ export declare class PlayerCamera {
156
+ #private;
157
+ /** @internal */
158
+ constructor(native: NativeServer, player: number);
159
+ /**
160
+ * Where their camera looks (a unit vector), as their last sync: where
161
+ * they aim, or what they look at. Null before it, and for passengers.
162
+ */
163
+ get front(): Vector3 | null;
164
+ /** Where their camera is, as their last sync; null as `front`. */
165
+ get position(): Vector3 | null;
166
+ /** One shot, gliding there from where the camera is over `ms`; resolves when it's there (false if replaced first). */
167
+ set(shot: CameraShot): Promise<boolean>;
168
+ /** Plays a sequence of shots, holds and paths on their game, in order. */
169
+ play(steps: readonly CameraStep[], options?: CameraPlayOptions): CameraSequence;
170
+ /**
171
+ * Lets them fly it: the mouse turns it, the movement keys move it, sprint
172
+ * goes up, crouch down, jump faster, the mouse wheel zooms. Their ped
173
+ * stays put meanwhile. `speed` in m/s (default 10). `reset()` ends it.
174
+ */
175
+ freecam(options?: {
176
+ speed?: number;
177
+ widescreen?: boolean;
178
+ }): void;
179
+ /** Stops whatever's playing (or the freecam): the camera stays where it is. */
180
+ stop(): void;
181
+ /** Back behind them, as normal. */
182
+ reset(): void;
183
+ /** @internal Their game's report: step `step` started (0), done (1), stopped (2). */
184
+ heard(id: number, step: number, kind: number): void;
185
+ /** @internal They left: whatever was playing stops. */
186
+ disconnected(): void;
187
+ }
188
+ export {};
package/dist/camera.js ADDED
@@ -0,0 +1,247 @@
1
+ // ---- The flat layout (as client/src/camera.cpp reads it) ------------------------
2
+ /** @internal Floats a step. */
3
+ export const STEP_FLOATS = 32;
4
+ /** @internal Floats a path point. */
5
+ export const POINT_FLOATS = 8;
6
+ const MAX_STEPS = 32;
7
+ const MAX_POINTS = 256;
8
+ const num = (v, what) => {
9
+ if (typeof v !== "number" || !Number.isFinite(v))
10
+ throw new TypeError(`camera: ${what} must be a number`);
11
+ return v;
12
+ };
13
+ const vec = (v, what) => {
14
+ const o = v;
15
+ if (!o || typeof o !== "object")
16
+ throw new TypeError(`camera: ${what} must be { x, y, z }`);
17
+ return { x: num(o.x, `${what}.x`), y: num(o.y, `${what}.y`), z: num(o.z, `${what}.z`) };
18
+ };
19
+ const easeOf = (e) => e === undefined || e === true || e === "inOut" ? 3 : e === false || e === "linear" ? 0 : e === "in" ? 1 : e === "out" ? 2 : 3;
20
+ const fovOf = (v) => Math.min(120, Math.max(5, num(v, "fov")));
21
+ // A spot or a thing: [kind, id, x, y, z] (kind 0 a spot, 1 a ped, 2 a player, 3 a vehicle).
22
+ function target(t, what) {
23
+ const o = t;
24
+ if (!o || typeof o !== "object")
25
+ throw new TypeError(`camera: ${what} must be a spot or { player | ped | vehicle }`);
26
+ const idOf = (x) => (typeof x === "number" ? x : num(x?.id, `${what}'s id`));
27
+ const kind = "ped" in o ? 1 : "player" in o ? 2 : "vehicle" in o ? 3 : 0;
28
+ if (!kind) {
29
+ const v = vec(o, what);
30
+ return [0, 0, v.x, v.y, v.z];
31
+ }
32
+ const off = o.offset === undefined ? { x: 0, y: 0, z: 0 } : vec(o.offset, `${what}.offset`);
33
+ return [kind, idOf(o.ped ?? o.player ?? o.vehicle), off.x, off.y, off.z];
34
+ }
35
+ /** @internal Steps as floats, for the player's game. */
36
+ export function encodeCamera(steps) {
37
+ if (!Array.isArray(steps) || steps.length === 0)
38
+ throw new TypeError("camera: at least one step");
39
+ if (steps.length > MAX_STEPS)
40
+ throw new RangeError(`camera: at most ${MAX_STEPS} steps`);
41
+ const out = [];
42
+ const points = [];
43
+ steps.forEach((step, i) => {
44
+ const s = step;
45
+ const f = new Array(STEP_FLOATS).fill(0);
46
+ f[10] = 7 /* Look.Keep */;
47
+ let flags = 0;
48
+ const focus = (v, aperture, where) => {
49
+ if (v === null)
50
+ f[24] = 1;
51
+ else if (v === "auto")
52
+ f[24] = 3;
53
+ else if (typeof v === "number")
54
+ (f[24] = 2), (f[30] = Math.max(0.1, num(v, `${where}.focus`)));
55
+ else if (v !== undefined) {
56
+ f[24] = 4;
57
+ [f[25], f[26], f[27], f[28], f[29]] = target(v, `${where}.focus`);
58
+ }
59
+ if (aperture !== undefined)
60
+ f[31] = Math.max(0.5, num(aperture, `${where}.aperture`));
61
+ };
62
+ const lookAt = (look, rotation, where, ahead) => {
63
+ if (rotation !== undefined) {
64
+ const r = rotation;
65
+ f[10] = 4 /* Look.Rotation */;
66
+ f[15] = num(r.pan, `${where}.rotation.pan`);
67
+ f[16] = r.tilt === undefined ? 0 : num(r.tilt, `${where}.rotation.tilt`);
68
+ }
69
+ else if (look === "ahead") {
70
+ f[10] = 5 /* Look.Ahead */;
71
+ }
72
+ else if (look !== undefined) {
73
+ const t = target(look, `${where}.lookAt`);
74
+ [f[10], f[11], f[12], f[13], f[14]] = t;
75
+ }
76
+ else if (ahead) {
77
+ f[10] = 5 /* Look.Ahead */;
78
+ }
79
+ };
80
+ if ("hold" in s) {
81
+ f[0] = 1;
82
+ f[1] = Math.max(0, num(s.hold, `step ${i}.hold`));
83
+ }
84
+ else if ("path" in s) {
85
+ const path = s.path;
86
+ if (!Array.isArray(path) || path.length < 2)
87
+ throw new TypeError(`camera: step ${i}.path needs at least 2 points`);
88
+ if (points.length / POINT_FLOATS + path.length > MAX_POINTS)
89
+ throw new RangeError(`camera: at most ${MAX_POINTS} path points in all`);
90
+ f[0] = 2;
91
+ f[1] = s.ms === undefined ? 0 : Math.max(0, num(s.ms, `step ${i}.ms`));
92
+ f[2] = s.speed === undefined ? 10 : Math.max(0.1, num(s.speed, `step ${i}.speed`));
93
+ f[3] = easeOf(s.ease);
94
+ f[4] = -1;
95
+ f[17] = s.lookAhead === undefined ? 5 : Math.max(0.5, num(s.lookAhead, `step ${i}.lookAhead`));
96
+ f[21] = points.length / POINT_FLOATS;
97
+ f[22] = path.length;
98
+ f[23] = s.smoothing === undefined ? 1 : Math.min(1, Math.max(0, num(s.smoothing, `step ${i}.smoothing`)));
99
+ const pointsTurn = path.every((p) => p.pan !== undefined);
100
+ const pointsRoll = path.some((p) => p.roll !== undefined);
101
+ const pointsFov = path.some((p) => p.fov !== undefined);
102
+ for (const [j, p] of path.entries()) {
103
+ const v = vec(p, `step ${i}.path[${j}]`);
104
+ points.push(v.x, v.y, v.z, p.pan ?? 0, p.tilt ?? 0, p.roll ?? 0, p.fov === undefined ? 70 : fovOf(p.fov), 0);
105
+ }
106
+ if (s.lookAt === undefined && s.rotation === undefined && pointsTurn)
107
+ f[10] = 6 /* Look.Points */;
108
+ else
109
+ lookAt(s.lookAt, s.rotation, `step ${i}`, true);
110
+ if (pointsRoll)
111
+ flags |= 8 /* Flag.PointRoll */;
112
+ else if (s.bank)
113
+ flags |= 4 /* Flag.Bank */;
114
+ else if (s.roll !== undefined)
115
+ (flags |= 1 /* Flag.Roll */), (f[19] = num(s.roll, `step ${i}.roll`));
116
+ if (pointsFov)
117
+ flags |= 16 /* Flag.PointFov */;
118
+ else if (s.fov !== undefined)
119
+ (flags |= 2 /* Flag.Fov */), (f[20] = fovOf(s.fov));
120
+ focus(s.focus, s.aperture, `step ${i}`);
121
+ }
122
+ else {
123
+ if (s.position === undefined)
124
+ throw new TypeError(`camera: step ${i} needs position, hold or path`);
125
+ f[0] = 0;
126
+ f[1] = s.ms === undefined ? 0 : Math.max(0, num(s.ms, `step ${i}.ms`));
127
+ f[3] = easeOf(s.ease);
128
+ const p = target(s.position, `step ${i}.position`);
129
+ [f[4], f[5], f[6], f[7], f[8]] = p;
130
+ f[9] = s.position.relative ? 1 : 0;
131
+ lookAt(s.lookAt, s.rotation, `step ${i}`, false);
132
+ if (s.roll !== undefined)
133
+ (flags |= 1 /* Flag.Roll */), (f[19] = num(s.roll, `step ${i}.roll`));
134
+ if (s.fov !== undefined)
135
+ (flags |= 2 /* Flag.Fov */), (f[20] = fovOf(s.fov));
136
+ focus(s.focus, s.aperture, `step ${i}`);
137
+ }
138
+ f[18] = flags;
139
+ out.push(...f);
140
+ });
141
+ return { steps: out, points };
142
+ }
143
+ /**
144
+ * A player's camera (`player.camera`): shots and glides between them,
145
+ * sequences of moves and paths played on their game, a freecam they fly, or
146
+ * behind them as normal. Position, what it looks at (or pan and tilt),
147
+ * roll and field of view. Client scripts have the same: `sagl.camera`.
148
+ *
149
+ * ```ts
150
+ * await player.camera.set({ position: { x: 1500, y: -1700, z: 60 }, lookAt: { x: 1480, y: -1750, z: 13 } });
151
+ * await player.camera.set({ position: { x: 1450, y: -1700, z: 40 }, lookAt: car, fov: 40, roll: 5, ms: 5000 });
152
+ * await player.camera.play([
153
+ * { path: [a, b, c, d], ms: 10000, bank: true },
154
+ * { hold: 2000 },
155
+ * ]).done;
156
+ * player.camera.reset();
157
+ * ```
158
+ */
159
+ export class PlayerCamera {
160
+ #native;
161
+ #player;
162
+ #next = 1;
163
+ #playing = null;
164
+ /** @internal */
165
+ constructor(native, player) {
166
+ this.#native = native;
167
+ this.#player = player;
168
+ }
169
+ /**
170
+ * Where their camera looks (a unit vector), as their last sync: where
171
+ * they aim, or what they look at. Null before it, and for passengers.
172
+ */
173
+ get front() {
174
+ return this.#native.player(this.#player)?.cameraFront ?? null;
175
+ }
176
+ /** Where their camera is, as their last sync; null as `front`. */
177
+ get position() {
178
+ return this.#native.player(this.#player)?.cameraPosition ?? null;
179
+ }
180
+ /** One shot, gliding there from where the camera is over `ms`; resolves when it's there (false if replaced first). */
181
+ set(shot) {
182
+ return this.play([shot], { widescreen: shot.widescreen }).done;
183
+ }
184
+ /** Plays a sequence of shots, holds and paths on their game, in order. */
185
+ play(steps, options = {}) {
186
+ const encoded = encodeCamera(steps);
187
+ const id = this.#next++;
188
+ let resolve;
189
+ const done = new Promise((r) => (resolve = r));
190
+ const listeners = new Set();
191
+ this.#replace({ id, done: resolve, steps: listeners });
192
+ this.#native.camera(this.#player, { id, ...encoded, loop: options.loop ?? false, widescreen: options.widescreen ?? false });
193
+ return {
194
+ done,
195
+ onStep: (fn) => {
196
+ listeners.add(fn);
197
+ return () => listeners.delete(fn);
198
+ },
199
+ stop: () => {
200
+ if (this.#playing?.id === id)
201
+ this.stop();
202
+ },
203
+ };
204
+ }
205
+ /**
206
+ * Lets them fly it: the mouse turns it, the movement keys move it, sprint
207
+ * goes up, crouch down, jump faster, the mouse wheel zooms. Their ped
208
+ * stays put meanwhile. `speed` in m/s (default 10). `reset()` ends it.
209
+ */
210
+ freecam(options = {}) {
211
+ this.#replace(null);
212
+ this.#native.camera(this.#player, { freecam: true, freecamSpeed: options.speed ?? 0, widescreen: options.widescreen ?? false });
213
+ }
214
+ /** Stops whatever's playing (or the freecam): the camera stays where it is. */
215
+ stop() {
216
+ this.#replace(null);
217
+ this.#native.camera(this.#player, { stop: true });
218
+ }
219
+ /** Back behind them, as normal. */
220
+ reset() {
221
+ this.#replace(null);
222
+ this.#native.camera(this.#player, { behind: true });
223
+ }
224
+ /** @internal Their game's report: step `step` started (0), done (1), stopped (2). */
225
+ heard(id, step, kind) {
226
+ const p = this.#playing;
227
+ if (!p || p.id !== id)
228
+ return;
229
+ if (kind === 0)
230
+ for (const fn of p.steps)
231
+ fn(step);
232
+ else {
233
+ this.#playing = null;
234
+ p.done(kind === 1);
235
+ }
236
+ }
237
+ /** @internal They left: whatever was playing stops. */
238
+ disconnected() {
239
+ this.#replace(null);
240
+ }
241
+ #replace(next) {
242
+ const old = this.#playing;
243
+ this.#playing = next;
244
+ old?.done(false);
245
+ }
246
+ }
247
+ //# sourceMappingURL=camera.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"camera.js","sourceRoot":"","sources":["../src/camera.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { Player } from "./player.js";
2
+ /**
3
+ * First come, first served (`server.claims`): one player at a time holds a
4
+ * thing (a payphone, a seat, a job), by any key you like. Let go with
5
+ * `release`, after `ms`, or when they leave.
6
+ *
7
+ * ```ts
8
+ * channel.on((player, msg) => {
9
+ * if (msg.answer && player.isNear(PHONE, 2) && server.claims.take("payphone", player, { ms: 15_000 })) {
10
+ * channel.broadcast({ answeredBy: player.id });
11
+ * }
12
+ * });
13
+ * ```
14
+ */
15
+ export declare class Claims {
16
+ #private;
17
+ /** True if they now hold it (it was free, or already theirs); false if someone else does. */
18
+ take(key: string, player: Player, options?: {
19
+ ms?: number;
20
+ }): boolean;
21
+ /** Lets go of it (only if `player` holds it, when given). */
22
+ release(key: string, player?: Player): void;
23
+ /** Who holds it, or null. */
24
+ holder(key: string): Player | null;
25
+ /** @internal A player left: what they held is free. */
26
+ forget(player: Player): void;
27
+ }
package/dist/claims.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * First come, first served (`server.claims`): one player at a time holds a
3
+ * thing (a payphone, a seat, a job), by any key you like. Let go with
4
+ * `release`, after `ms`, or when they leave.
5
+ *
6
+ * ```ts
7
+ * channel.on((player, msg) => {
8
+ * if (msg.answer && player.isNear(PHONE, 2) && server.claims.take("payphone", player, { ms: 15_000 })) {
9
+ * channel.broadcast({ answeredBy: player.id });
10
+ * }
11
+ * });
12
+ * ```
13
+ */
14
+ export class Claims {
15
+ #held = new Map();
16
+ /** True if they now hold it (it was free, or already theirs); false if someone else does. */
17
+ take(key, player, options = {}) {
18
+ const held = this.#held.get(key);
19
+ if (held && held.player !== player && held.player.connected)
20
+ return false;
21
+ if (held?.timer)
22
+ clearTimeout(held.timer);
23
+ const timer = options.ms ? setTimeout(() => this.release(key), options.ms) : null;
24
+ this.#held.set(key, { player, timer });
25
+ return true;
26
+ }
27
+ /** Lets go of it (only if `player` holds it, when given). */
28
+ release(key, player) {
29
+ const held = this.#held.get(key);
30
+ if (!held || (player && held.player !== player))
31
+ return;
32
+ if (held.timer)
33
+ clearTimeout(held.timer);
34
+ this.#held.delete(key);
35
+ }
36
+ /** Who holds it, or null. */
37
+ holder(key) {
38
+ const held = this.#held.get(key);
39
+ return held && held.player.connected ? held.player : null;
40
+ }
41
+ /** @internal A player left: what they held is free. */
42
+ forget(player) {
43
+ for (const [key, held] of [...this.#held])
44
+ if (held.player === player)
45
+ this.release(key);
46
+ }
47
+ }
48
+ //# sourceMappingURL=claims.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims.js","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,MAAM;IACjB,KAAK,GAAG,IAAI,GAAG,EAA2E,CAAC;IAE3F,6FAA6F;IAC7F,IAAI,CAAC,GAAW,EAAE,MAAc,EAAE,UAA2B,EAAE;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAC1E,IAAI,IAAI,EAAE,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6DAA6D;IAC7D,OAAO,CAAC,GAAW,EAAE,MAAe;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC;YAAE,OAAO;QACxD,IAAI,IAAI,CAAC,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,6BAA6B;IAC7B,MAAM,CAAC,GAAW;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,OAAO,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,CAAC;IAED,uDAAuD;IACvD,MAAM,CAAC,MAAc;QACnB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;YAAE,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM;gBAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3F,CAAC;CACF"}
@@ -0,0 +1,135 @@
1
+ import type { Player } from "./player.js";
2
+ import type { Vehicle } from "./vehicle.js";
3
+ /** A command's usage went wrong: the message is shown to the player. */
4
+ export declare class CommandError extends Error {
5
+ }
6
+ /**
7
+ * What an argument takes: how it's read from what was typed, how the chat
8
+ * suggests it, and how it's shown in usage. Made with `arg.*`.
9
+ */
10
+ export interface ArgType<T> {
11
+ /** As the chat shows it in usage ("player", "1-100"...). */
12
+ readonly label: string;
13
+ /** @internal The client's token (type[:params]). */
14
+ readonly token: string;
15
+ /** Takes the rest of the line (text). */
16
+ readonly greedy?: boolean;
17
+ /** Reads it; throws `CommandError` if it can't. */
18
+ parse(input: string, player: Player): T;
19
+ /** Suggestions the server makes for it (custom types): the chat asks as they type. */
20
+ suggest?(player: Player, partial: string): string[] | Promise<string[]>;
21
+ }
22
+ /** @internal Players, to resolve `arg.player()` and `arg.vehicle()`. */
23
+ export interface Lookup {
24
+ players(): Player[];
25
+ vehicle(id: number): Vehicle | undefined;
26
+ }
27
+ /** @internal */
28
+ export declare function setLookup(l: Lookup): void;
29
+ /** Argument types for `command(...).argument(name, type)`. */
30
+ export declare const arg: {
31
+ /** A player: by id, their name, or the start of it (one match). */
32
+ player(): ArgType<Player>;
33
+ /** A whole number, within `min`-`max`. */
34
+ integer(o?: {
35
+ min?: number;
36
+ max?: number;
37
+ }): ArgType<number>;
38
+ /** A number (decimals too), within `min`-`max`. */
39
+ number(o?: {
40
+ min?: number;
41
+ max?: number;
42
+ }): ArgType<number>;
43
+ /** One word. */
44
+ word(): ArgType<string>;
45
+ /** The rest of the line (it must come last). */
46
+ text(): ArgType<string>;
47
+ /** yes/no, true/false, on/off, 1/0. */
48
+ boolean(): ArgType<boolean>;
49
+ /** One of these words. */
50
+ choice<T extends string>(choices: readonly T[]): ArgType<T>;
51
+ /** A vehicle, by its id. */
52
+ vehicle(): ArgType<Vehicle>;
53
+ /**
54
+ * Your own: `parse` reads it (throw `CommandError` to refuse), `suggest`
55
+ * offers what the chat suggests as they type (asked of the server).
56
+ */
57
+ custom<T>(o: {
58
+ label: string;
59
+ parse(input: string, player: Player): T;
60
+ suggest?(player: Player, partial: string): string[] | Promise<string[]>;
61
+ greedy?: boolean;
62
+ }): ArgType<T>;
63
+ };
64
+ interface ArgDef {
65
+ name: string;
66
+ type: ArgType<unknown>;
67
+ optional: boolean;
68
+ }
69
+ /** What a command's executor gets: its arguments by name. */
70
+ export type CommandArgs = Record<string, unknown>;
71
+ export type Executor = (player: Player, args: CommandArgs, line: string) => void | Promise<void>;
72
+ /**
73
+ * A command, built up (as Minecraft's Brigadier): its name, aliases,
74
+ * arguments, subcommands, who may use it, and what it does. Made with
75
+ * `command(name)`.
76
+ *
77
+ * ```ts
78
+ * server.commands.register(
79
+ * command("pay").description("Give money to a player")
80
+ * .argument("player", arg.player())
81
+ * .argument("amount", arg.integer({ min: 1 }))
82
+ * .executes((player, { player: to, amount }) => { ... }),
83
+ * );
84
+ * ```
85
+ */
86
+ export declare class CommandBuilder {
87
+ /** @internal */ readonly name: string;
88
+ /** @internal */ aliases: string[];
89
+ /** @internal */ text: string;
90
+ /** @internal */ check: ((player: Player) => boolean) | null;
91
+ /** @internal */ args: ArgDef[];
92
+ /** @internal */ children: CommandBuilder[];
93
+ /** @internal */ run: Executor | null;
94
+ /** @internal */
95
+ constructor(name: string);
96
+ /** Other names for it. */
97
+ alias(...names: string[]): this;
98
+ /** What it does, shown with its usage in the chat's suggestions. */
99
+ description(text: string): this;
100
+ /** Who may use it (and see it suggested): checked per player. */
101
+ requires(check: (player: Player) => boolean): this;
102
+ /** The next argument. Optional ones come last. */
103
+ argument(name: string, type: ArgType<unknown>, options?: {
104
+ optional?: boolean;
105
+ }): this;
106
+ /** A subcommand: `/faction invite ...` is `command("faction").then(command("invite")...)`. */
107
+ then(sub: CommandBuilder): this;
108
+ /** What it does: `fn(player, args, line)`; throw `CommandError` to tell them what's wrong. */
109
+ executes(fn: Executor): this;
110
+ }
111
+ /** Starts a command: see `CommandBuilder`. */
112
+ export declare function command(name: string): CommandBuilder;
113
+ /** `server.commands`: the server's chat commands. */
114
+ export declare class Commands {
115
+ #private;
116
+ /** @internal */
117
+ constructor(send: (player: Player, tree: string) => void, players: () => Player[], error: (player: Player, text: string) => void);
118
+ /** Adds commands (players' chat suggests them at once). */
119
+ register(...commands: CommandBuilder[]): this;
120
+ /** Removes a command, by its name. */
121
+ unregister(name: string): void;
122
+ /** Sends their chat the commands they can use now: after what `requires` checks changes (their admin level...). */
123
+ refresh(player: Player): void;
124
+ /**
125
+ * @internal A /command line from `player`: true if a registered command
126
+ * took it (run, or its usage error shown), false if none is called that.
127
+ */
128
+ handle(player: Player, line: string): Promise<boolean>;
129
+ /**
130
+ * @internal Suggestions for the custom argument being typed at the end of
131
+ * `line`: [where its word starts, suggestions], or null.
132
+ */
133
+ suggest(player: Player, line: string): Promise<[number, string[]] | null>;
134
+ }
135
+ export {};