1681-engine 0.5.9 → 0.6.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.
Files changed (210) hide show
  1. package/CHANGELOG.md +92 -1
  2. package/README.md +15 -6
  3. package/dist/1681-engine.js +588 -465
  4. package/dist/ai/behaviorTree.js +198 -0
  5. package/dist/ai/buildTree.js +54 -0
  6. package/dist/ambient/life/Birds.js +73 -0
  7. package/dist/ambient/life/Butterflies.js +43 -0
  8. package/dist/ambient/life/ChimneySmoke.js +50 -0
  9. package/dist/ambient/life/Drift.js +75 -0
  10. package/dist/ambient/life/Fireflies.js +52 -0
  11. package/dist/ambient/life/lifeMotion.js +49 -0
  12. package/dist/assets/AssetLoader.js +115 -70
  13. package/dist/assets/Prepainter.js +61 -0
  14. package/dist/assets/workerPainter.js +39 -0
  15. package/dist/audio/spatial.js +118 -0
  16. package/dist/cjs/electron/electronLike.d.ts +55 -0
  17. package/dist/cjs/electron/electronLike.js +7 -0
  18. package/dist/cjs/electron/index.d.ts +14 -0
  19. package/dist/cjs/electron/index.js +20 -0
  20. package/dist/cjs/electron/lockdown.d.ts +33 -0
  21. package/dist/cjs/electron/lockdown.js +69 -0
  22. package/dist/cjs/electron/lockdownRules.d.ts +28 -0
  23. package/dist/cjs/electron/lockdownRules.js +61 -0
  24. package/dist/cjs/electron/sessionStore.d.ts +40 -0
  25. package/dist/cjs/electron/sessionStore.js +77 -0
  26. package/dist/cjs/electron/shellId.d.ts +22 -0
  27. package/dist/cjs/electron/shellId.js +31 -0
  28. package/dist/cjs/electron/webFiles.d.ts +13 -0
  29. package/dist/cjs/electron/webFiles.js +52 -0
  30. package/dist/cjs/electron/webPatcher.d.ts +83 -0
  31. package/dist/cjs/electron/webPatcher.js +223 -0
  32. package/dist/cjs/electron/webPointers.d.ts +19 -0
  33. package/dist/cjs/electron/webPointers.js +35 -0
  34. package/dist/cjs/package.json +1 -0
  35. package/dist/cjs/updates/index.d.ts +8 -0
  36. package/dist/cjs/updates/index.js +21 -0
  37. package/dist/cjs/updates/manifest.d.ts +73 -0
  38. package/dist/cjs/updates/manifest.js +67 -0
  39. package/dist/cjs/updates/pickUpdate.d.ts +42 -0
  40. package/dist/cjs/updates/pickUpdate.js +52 -0
  41. package/dist/cjs/updates/webPlan.d.ts +20 -0
  42. package/dist/cjs/updates/webPlan.js +34 -0
  43. package/dist/dialogue/DialogueRunner.js +173 -0
  44. package/dist/dialogue/expr.js +137 -0
  45. package/dist/dialogue/validateDialogue.js +52 -0
  46. package/dist/ecs/prefab.js +94 -0
  47. package/dist/electron/lockdown.js +31 -0
  48. package/dist/electron/lockdownRules.js +42 -0
  49. package/dist/electron/sessionStore.js +48 -0
  50. package/dist/electron/shellId.js +18 -0
  51. package/dist/electron/webFiles.js +36 -0
  52. package/dist/electron/webPatcher.js +153 -0
  53. package/dist/electron/webPointers.js +25 -0
  54. package/dist/electron.js +19 -0
  55. package/dist/input/Actions.js +58 -27
  56. package/dist/input/InputCapture.js +98 -0
  57. package/dist/input/Keymap.js +32 -26
  58. package/dist/input/haptics.js +50 -0
  59. package/dist/input/inputTape.js +68 -0
  60. package/dist/mobile/backButton.js +40 -0
  61. package/dist/mobile/capacitor.js +48 -0
  62. package/dist/mobile/screen.js +31 -0
  63. package/dist/mobile.js +12 -0
  64. package/dist/nav/flowField.js +58 -0
  65. package/dist/nav/steering.js +77 -0
  66. package/dist/net/ApiClient.js +96 -0
  67. package/dist/net/InterpolationBuffer.js +30 -23
  68. package/dist/net/LagCompensator.js +100 -0
  69. package/dist/net/Room.js +122 -43
  70. package/dist/net/RoomHost.js +13 -4
  71. package/dist/net/SpatialHash.js +66 -0
  72. package/dist/pixel/lifeArt.js +83 -0
  73. package/dist/pixel.js +63 -58
  74. package/dist/react/ConfirmButton.js +24 -0
  75. package/dist/react/baseCss.js +1 -0
  76. package/dist/react/labels.js +7 -6
  77. package/dist/react/useJsonSelector.js +13 -0
  78. package/dist/react.js +73 -68
  79. package/dist/tilemap/TilemapView.js +57 -32
  80. package/dist/tilemap/autotile.js +103 -0
  81. package/dist/tilemap/collision.js +29 -18
  82. package/dist/tilemap/ldtk.js +21 -0
  83. package/dist/tilemap/ldtkParse.js +191 -0
  84. package/dist/types/ai/behaviorTree.d.ts +133 -0
  85. package/dist/types/ai/behaviorTree.d.ts.map +1 -0
  86. package/dist/types/ai/buildTree.d.ts +55 -0
  87. package/dist/types/ai/buildTree.d.ts.map +1 -0
  88. package/dist/types/ambient/life/Birds.d.ts +50 -0
  89. package/dist/types/ambient/life/Birds.d.ts.map +1 -0
  90. package/dist/types/ambient/life/Butterflies.d.ts +32 -0
  91. package/dist/types/ambient/life/Butterflies.d.ts.map +1 -0
  92. package/dist/types/ambient/life/ChimneySmoke.d.ts +37 -0
  93. package/dist/types/ambient/life/ChimneySmoke.d.ts.map +1 -0
  94. package/dist/types/ambient/life/Drift.d.ts +58 -0
  95. package/dist/types/ambient/life/Drift.d.ts.map +1 -0
  96. package/dist/types/ambient/life/Fireflies.d.ts +43 -0
  97. package/dist/types/ambient/life/Fireflies.d.ts.map +1 -0
  98. package/dist/types/ambient/life/lifeMotion.d.ts +63 -0
  99. package/dist/types/ambient/life/lifeMotion.d.ts.map +1 -0
  100. package/dist/types/assets/AssetLoader.d.ts +20 -0
  101. package/dist/types/assets/AssetLoader.d.ts.map +1 -1
  102. package/dist/types/assets/Prepainter.d.ts +64 -0
  103. package/dist/types/assets/Prepainter.d.ts.map +1 -0
  104. package/dist/types/assets/workerPainter.d.ts +21 -0
  105. package/dist/types/assets/workerPainter.d.ts.map +1 -0
  106. package/dist/types/audio/spatial.d.ts +107 -0
  107. package/dist/types/audio/spatial.d.ts.map +1 -0
  108. package/dist/types/dialogue/DialogueRunner.d.ts +78 -0
  109. package/dist/types/dialogue/DialogueRunner.d.ts.map +1 -0
  110. package/dist/types/dialogue/expr.d.ts +12 -0
  111. package/dist/types/dialogue/expr.d.ts.map +1 -0
  112. package/dist/types/dialogue/script.d.ts +78 -0
  113. package/dist/types/dialogue/script.d.ts.map +1 -0
  114. package/dist/types/dialogue/validateDialogue.d.ts +21 -0
  115. package/dist/types/dialogue/validateDialogue.d.ts.map +1 -0
  116. package/dist/types/ecs/prefab.d.ts +84 -0
  117. package/dist/types/ecs/prefab.d.ts.map +1 -0
  118. package/dist/types/electron/electronLike.d.ts +56 -0
  119. package/dist/types/electron/electronLike.d.ts.map +1 -0
  120. package/dist/types/electron/index.d.ts +15 -0
  121. package/dist/types/electron/index.d.ts.map +1 -0
  122. package/dist/types/electron/lockdown.d.ts +34 -0
  123. package/dist/types/electron/lockdown.d.ts.map +1 -0
  124. package/dist/types/electron/lockdownRules.d.ts +29 -0
  125. package/dist/types/electron/lockdownRules.d.ts.map +1 -0
  126. package/dist/types/electron/sessionStore.d.ts +41 -0
  127. package/dist/types/electron/sessionStore.d.ts.map +1 -0
  128. package/dist/types/electron/shellId.d.ts +23 -0
  129. package/dist/types/electron/shellId.d.ts.map +1 -0
  130. package/dist/types/electron/webFiles.d.ts +14 -0
  131. package/dist/types/electron/webFiles.d.ts.map +1 -0
  132. package/dist/types/electron/webPatcher.d.ts +84 -0
  133. package/dist/types/electron/webPatcher.d.ts.map +1 -0
  134. package/dist/types/electron/webPointers.d.ts +20 -0
  135. package/dist/types/electron/webPointers.d.ts.map +1 -0
  136. package/dist/types/index.d.ts +30 -3
  137. package/dist/types/index.d.ts.map +1 -1
  138. package/dist/types/input/Actions.d.ts +14 -0
  139. package/dist/types/input/Actions.d.ts.map +1 -1
  140. package/dist/types/input/InputCapture.d.ts +53 -0
  141. package/dist/types/input/InputCapture.d.ts.map +1 -0
  142. package/dist/types/input/Keymap.d.ts +12 -6
  143. package/dist/types/input/Keymap.d.ts.map +1 -1
  144. package/dist/types/input/haptics.d.ts +42 -0
  145. package/dist/types/input/haptics.d.ts.map +1 -0
  146. package/dist/types/input/inputTape.d.ts +66 -0
  147. package/dist/types/input/inputTape.d.ts.map +1 -0
  148. package/dist/types/mobile/backButton.d.ts +30 -0
  149. package/dist/types/mobile/backButton.d.ts.map +1 -0
  150. package/dist/types/mobile/capacitor.d.ts +62 -0
  151. package/dist/types/mobile/capacitor.d.ts.map +1 -0
  152. package/dist/types/mobile/index.d.ts +4 -0
  153. package/dist/types/mobile/index.d.ts.map +1 -0
  154. package/dist/types/mobile/screen.d.ts +27 -0
  155. package/dist/types/mobile/screen.d.ts.map +1 -0
  156. package/dist/types/nav/flowField.d.ts +31 -0
  157. package/dist/types/nav/flowField.d.ts.map +1 -0
  158. package/dist/types/nav/steering.d.ts +47 -0
  159. package/dist/types/nav/steering.d.ts.map +1 -0
  160. package/dist/types/net/ApiClient.d.ts +74 -0
  161. package/dist/types/net/ApiClient.d.ts.map +1 -0
  162. package/dist/types/net/InterpolationBuffer.d.ts +5 -0
  163. package/dist/types/net/InterpolationBuffer.d.ts.map +1 -1
  164. package/dist/types/net/LagCompensator.d.ts +70 -0
  165. package/dist/types/net/LagCompensator.d.ts.map +1 -0
  166. package/dist/types/net/Room.d.ts +72 -3
  167. package/dist/types/net/Room.d.ts.map +1 -1
  168. package/dist/types/net/RoomHost.d.ts +8 -3
  169. package/dist/types/net/RoomHost.d.ts.map +1 -1
  170. package/dist/types/net/SpatialHash.d.ts +25 -0
  171. package/dist/types/net/SpatialHash.d.ts.map +1 -0
  172. package/dist/types/pixel/index.d.ts +1 -0
  173. package/dist/types/pixel/index.d.ts.map +1 -1
  174. package/dist/types/pixel/lifeArt.d.ts +63 -0
  175. package/dist/types/pixel/lifeArt.d.ts.map +1 -0
  176. package/dist/types/react/ConfirmButton.d.ts +26 -0
  177. package/dist/types/react/ConfirmButton.d.ts.map +1 -0
  178. package/dist/types/react/baseCss.d.ts +1 -1
  179. package/dist/types/react/baseCss.d.ts.map +1 -1
  180. package/dist/types/react/index.d.ts +2 -0
  181. package/dist/types/react/index.d.ts.map +1 -1
  182. package/dist/types/react/labels.d.ts +2 -0
  183. package/dist/types/react/labels.d.ts.map +1 -1
  184. package/dist/types/react/useJsonSelector.d.ts +13 -0
  185. package/dist/types/react/useJsonSelector.d.ts.map +1 -0
  186. package/dist/types/tilemap/TilemapView.d.ts +17 -0
  187. package/dist/types/tilemap/TilemapView.d.ts.map +1 -1
  188. package/dist/types/tilemap/autotile.d.ts +95 -0
  189. package/dist/types/tilemap/autotile.d.ts.map +1 -0
  190. package/dist/types/tilemap/collision.d.ts +8 -0
  191. package/dist/types/tilemap/collision.d.ts.map +1 -1
  192. package/dist/types/tilemap/ldtk.d.ts +97 -0
  193. package/dist/types/tilemap/ldtk.d.ts.map +1 -0
  194. package/dist/types/tilemap/ldtkParse.d.ts +26 -0
  195. package/dist/types/tilemap/ldtkParse.d.ts.map +1 -0
  196. package/dist/types/ui/ScrollView.d.ts.map +1 -1
  197. package/dist/types/updates/index.d.ts +9 -0
  198. package/dist/types/updates/index.d.ts.map +1 -0
  199. package/dist/types/updates/manifest.d.ts +74 -0
  200. package/dist/types/updates/manifest.d.ts.map +1 -0
  201. package/dist/types/updates/pickUpdate.d.ts +43 -0
  202. package/dist/types/updates/pickUpdate.d.ts.map +1 -0
  203. package/dist/types/updates/webPlan.d.ts +21 -0
  204. package/dist/types/updates/webPlan.d.ts.map +1 -0
  205. package/dist/ui/ScrollView.js +10 -8
  206. package/dist/updates/manifest.js +35 -0
  207. package/dist/updates/pickUpdate.js +27 -0
  208. package/dist/updates/webPlan.js +14 -0
  209. package/dist/updates.js +15 -0
  210. package/package.json +35 -3
@@ -0,0 +1,68 @@
1
+ class r {
2
+ constructor(t, e) {
3
+ this.meta = e, this.untap = t.tap((s) => this.capture(s));
4
+ }
5
+ meta;
6
+ order = [];
7
+ index = /* @__PURE__ */ new Map();
8
+ last = /* @__PURE__ */ new Map();
9
+ changes = [];
10
+ steps = 0;
11
+ untap;
12
+ stopped = null;
13
+ /** Steps recorded so far. */
14
+ get length() {
15
+ return this.steps;
16
+ }
17
+ /** Stops recording and returns the tape (the same one on every later call). */
18
+ stop() {
19
+ return this.stopped ? this.stopped : (this.untap(), this.stopped = { version: 1, actions: [...this.order], steps: this.steps, changes: this.changes.map((t) => [...t]) }, this.meta && (this.stopped.meta = structuredClone(this.meta)), this.stopped);
20
+ }
21
+ capture(t) {
22
+ const e = this.steps++;
23
+ for (const [s, i] of t) this.note(e, s, i);
24
+ for (const [s, i] of this.last) i !== 0 && !t.has(s) && this.note(e, s, 0);
25
+ }
26
+ note(t, e, s) {
27
+ if ((this.last.get(e) ?? 0) === s) return;
28
+ let i = this.index.get(e);
29
+ i === void 0 && (i = this.order.length, this.order.push(e), this.index.set(e, i)), this.last.set(e, s), this.changes.push([t, i, s]);
30
+ }
31
+ }
32
+ class h {
33
+ constructor(t) {
34
+ if (this.tape = t, !(t?.version === 1 && Array.isArray(t.actions) && Number.isInteger(t.steps) && Array.isArray(t.changes) && t.changes.every((s, i) => Array.isArray(s) && s.length === 3 && s.every(Number.isFinite) && s[1] >= 0 && s[1] < t.actions.length && (i === 0 || s[0] >= t.changes[i - 1][0])))) throw new Error("InputPlayer: not an input tape (version 1)");
35
+ }
36
+ tape;
37
+ step = 0;
38
+ next = 0;
39
+ values = /* @__PURE__ */ new Map();
40
+ /** Steps played so far. */
41
+ get position() {
42
+ return this.step;
43
+ }
44
+ get done() {
45
+ return this.step >= this.tape.steps;
46
+ }
47
+ /** The next step's values, or null once the tape is over. */
48
+ read() {
49
+ if (this.done) return null;
50
+ const t = this.tape.changes;
51
+ for (; this.next < t.length && t[this.next][0] === this.step; ) {
52
+ const [, e, s] = t[this.next++], i = this.tape.actions[e];
53
+ s === 0 ? this.values.delete(i) : this.values.set(i, s);
54
+ }
55
+ return this.step++, this.values;
56
+ }
57
+ /** Drives `actions` from the tape until it ends; `onEnd` is called on the poll that finds it over. */
58
+ playInto(t, e) {
59
+ t.replay(() => {
60
+ const s = this.read();
61
+ return s === null && e?.(), s;
62
+ });
63
+ }
64
+ }
65
+ export {
66
+ h as InputPlayer,
67
+ r as InputRecorder
68
+ };
@@ -0,0 +1,40 @@
1
+ class r {
2
+ constructor(t = () => {
3
+ }) {
4
+ this.onRoot = t;
5
+ }
6
+ onRoot;
7
+ handlers = [];
8
+ /** Puts `handler` on top; the returned function takes it off (from anywhere in the stack). */
9
+ push(t) {
10
+ return this.handlers.push(t), () => {
11
+ const s = this.handlers.lastIndexOf(t);
12
+ s >= 0 && this.handlers.splice(s, 1);
13
+ };
14
+ }
15
+ get size() {
16
+ return this.handlers.length;
17
+ }
18
+ /** A back press: offered from the top down; `onRoot` when none uses it. True when a handler used it. */
19
+ press() {
20
+ for (let t = this.handlers.length - 1; t >= 0; t--)
21
+ if (this.handlers[t]()) return !0;
22
+ return this.onRoot(), !1;
23
+ }
24
+ }
25
+ function h(n) {
26
+ const t = n.withinMs ?? 2e3, s = n.now ?? (() => Date.now());
27
+ let e = -1 / 0;
28
+ return () => {
29
+ const i = s();
30
+ if (i - e <= t) {
31
+ e = -1 / 0, n.exit();
32
+ return;
33
+ }
34
+ e = i, n.notify();
35
+ };
36
+ }
37
+ export {
38
+ r as BackStack,
39
+ h as doubleBackToExit
40
+ };
@@ -0,0 +1,48 @@
1
+ async function i(e, n) {
2
+ const t = await e.addListener("backButton", () => {
3
+ n.press();
4
+ });
5
+ return () => {
6
+ t.remove();
7
+ };
8
+ }
9
+ async function s(e) {
10
+ if (!e?.getInfo) return 1 / 0;
11
+ try {
12
+ const n = parseInt((await e.getInfo()).build, 10);
13
+ return Number.isFinite(n) ? n : 0;
14
+ } catch {
15
+ return 1 / 0;
16
+ }
17
+ }
18
+ function u(e) {
19
+ if (!/^[a-zA-Z][\w]*(\.[a-zA-Z][\w]*)+$/.test(e.appId))
20
+ throw new Error(`capacitorConfig: appId must be reverse-domain, like com.example.game (got '${e.appId}')`);
21
+ const n = e.backgroundColor ?? "#000000", t = e.debug ?? !1, a = {
22
+ appId: e.appId,
23
+ appName: e.appName,
24
+ webDir: e.webDir ?? "dist",
25
+ backgroundColor: n,
26
+ server: { androidScheme: "https", cleartext: !1 },
27
+ android: { backgroundColor: n, allowMixedContent: !1, captureInput: !0, webContentsDebuggingEnabled: t },
28
+ ios: { backgroundColor: n, contentInset: "never", scrollEnabled: !1, webContentsDebuggingEnabled: t },
29
+ plugins: {
30
+ SplashScreen: { launchAutoHide: !1, backgroundColor: n, showSpinner: !1 },
31
+ CapacitorUpdater: { autoUpdate: !1 }
32
+ }
33
+ };
34
+ return c(a, e.extra ?? {});
35
+ }
36
+ function c(e, n) {
37
+ const t = { ...e };
38
+ for (const [a, r] of Object.entries(n)) {
39
+ const o = t[a];
40
+ t[a] = r && typeof r == "object" && !Array.isArray(r) && o && typeof o == "object" && !Array.isArray(o) ? c(o, r) : r;
41
+ }
42
+ return t;
43
+ }
44
+ export {
45
+ u as capacitorConfig,
46
+ i as installBackButton,
47
+ s as nativeBuildOf
48
+ };
@@ -0,0 +1,31 @@
1
+ function r(n = globalThis.document) {
2
+ if (!n?.body) return { top: 0, right: 0, bottom: 0, left: 0 };
3
+ const t = n.createElement("div");
4
+ t.style.cssText = "position:fixed;visibility:hidden;pointer-events:none;padding-top:env(safe-area-inset-top,0px);padding-right:env(safe-area-inset-right,0px);padding-bottom:env(safe-area-inset-bottom,0px);padding-left:env(safe-area-inset-left,0px)", n.body.appendChild(t);
5
+ const e = getComputedStyle(t), i = (o) => parseFloat(o) || 0, a = { top: i(e.paddingTop), right: i(e.paddingRight), bottom: i(e.paddingBottom), left: i(e.paddingLeft) };
6
+ return t.remove(), a;
7
+ }
8
+ async function l(n = globalThis.navigator?.wakeLock, t = globalThis.document) {
9
+ if (!n) return () => {
10
+ };
11
+ let e = null, i = !1;
12
+ const a = async () => {
13
+ try {
14
+ const s = await n.request("screen");
15
+ if (i) return void s.release();
16
+ e = s, s.addEventListener?.("release", () => {
17
+ e === s && (e = null);
18
+ });
19
+ } catch {
20
+ }
21
+ }, o = () => {
22
+ t?.visibilityState === "visible" && !e && a();
23
+ };
24
+ return await a(), t?.addEventListener("visibilitychange", o), () => {
25
+ i = !0, t?.removeEventListener("visibilitychange", o), e?.release(), e = null;
26
+ };
27
+ }
28
+ export {
29
+ l as keepScreenOn,
30
+ r as safeAreaInsets
31
+ };
package/dist/mobile.js ADDED
@@ -0,0 +1,12 @@
1
+ import { BackStack as t, doubleBackToExit as a } from "./mobile/backButton.js";
2
+ import { capacitorConfig as c, installBackButton as n, nativeBuildOf as f } from "./mobile/capacitor.js";
3
+ import { keepScreenOn as k, safeAreaInsets as p } from "./mobile/screen.js";
4
+ export {
5
+ t as BackStack,
6
+ c as capacitorConfig,
7
+ a as doubleBackToExit,
8
+ n as installBackButton,
9
+ k as keepScreenOn,
10
+ f as nativeBuildOf,
11
+ p as safeAreaInsets
12
+ };
@@ -0,0 +1,58 @@
1
+ import { MinHeap as C } from "./MinHeap.js";
2
+ import { isOpen as g, NAV_STEPS as S, canStep as E } from "./navGrid.js";
3
+ function M(o, s, w = {}) {
4
+ const { cost: r, endOnly: l, maxCost: h = 1 / 0 } = w, i = o.width, e = i * o.height, u = new Float32Array(e).fill(1 / 0), x = new Int8Array(e).fill(-1), A = new Uint8Array(e), y = new C(), d = new Uint8Array(e);
5
+ for (const n of s) {
6
+ if (!g(o, n.x, n.y)) continue;
7
+ const t = n.y * i + n.x;
8
+ d[t] = 1, u[t] = 0, y.push(t, 0);
9
+ }
10
+ const k = (n, t) => d[t * i + n] === 1;
11
+ for (; y.size > 0; ) {
12
+ const n = y.pop();
13
+ if (A[n]) continue;
14
+ A[n] = 1;
15
+ const t = n % i, f = n / i | 0;
16
+ if (!(!d[n] && l?.(t, f)))
17
+ for (let c = 0; c < S.length; c++) {
18
+ const [T, U, z] = S[c], I = t - T, F = f - U;
19
+ if (!g(o, I, F) || !E(o, I, F, T, U, l, k)) continue;
20
+ const p = F * i + I;
21
+ if (A[p]) continue;
22
+ const a = u[n] + z + (r ? r(t, f) : 0);
23
+ a >= u[p] || a > h || (u[p] = a, x[p] = c, y.push(p, a));
24
+ }
25
+ }
26
+ const O = (n, t) => n >= 0 && t >= 0 && n < i && t < o.height;
27
+ return {
28
+ width: i,
29
+ height: o.height,
30
+ costs: u,
31
+ steps: x,
32
+ stepAt(n, t) {
33
+ if (!O(n, t)) return null;
34
+ const f = x[t * i + n];
35
+ if (f < 0) return null;
36
+ const c = S[f];
37
+ return [c[0], c[1]];
38
+ },
39
+ costAt(n, t) {
40
+ return O(n, t) ? u[t * i + n] : 1 / 0;
41
+ }
42
+ };
43
+ }
44
+ function N(o, s, w = o.width * o.height) {
45
+ if (o.costAt(s.x, s.y) === 1 / 0) return null;
46
+ const r = [{ x: s.x, y: s.y }];
47
+ let l = s.x, h = s.y;
48
+ for (let i = 0; i < w; i++) {
49
+ const e = o.stepAt(l, h);
50
+ if (!e) return r;
51
+ l += e[0], h += e[1], r.push({ x: l, y: h });
52
+ }
53
+ return r;
54
+ }
55
+ export {
56
+ M as flowField,
57
+ N as followField
58
+ };
@@ -0,0 +1,77 @@
1
+ const M = () => ({ x: 0, y: 0 });
2
+ function h(o, x, t, y) {
3
+ const n = Math.hypot(o, x);
4
+ return n === 0 ? { x: -y.vx, y: -y.vy } : { x: o / n * t - y.vx, y: x / n * t - y.vy };
5
+ }
6
+ function b(o, x, t, y) {
7
+ return h(x - o.x, t - o.y, y, o);
8
+ }
9
+ function I(o, x, t, y, n = 1 / 0) {
10
+ const r = o.x - x, f = o.y - t;
11
+ return r * r + f * f > n * n ? M() : h(r, f, y, o);
12
+ }
13
+ function w(o, x, t, y, n) {
14
+ const r = x - o.x, f = t - o.y, c = Math.hypot(r, f), v = c < n ? y * (c / n) : y;
15
+ return h(r, f, v, o);
16
+ }
17
+ function A(o, x, t, y) {
18
+ let n = 0, r = 0;
19
+ for (const f of x) {
20
+ if (f === o) continue;
21
+ let c = o.x - f.x, v = o.y - f.y, i = Math.hypot(c, v);
22
+ if (i >= t) continue;
23
+ i === 0 ? (c = o.vx - f.vx || 1, v = o.vy - f.vy, i = Math.hypot(c, v), c /= i, v /= i, i = 0) : (c /= i, v /= i);
24
+ const s = (1 - i / t) * y;
25
+ n += c * s, r += v * s;
26
+ }
27
+ return { x: n, y: r };
28
+ }
29
+ function k(o, x, t) {
30
+ let y = 0, n = 0, r = 0;
31
+ for (const f of x)
32
+ f === o || (f.x - o.x) ** 2 + (f.y - o.y) ** 2 > t * t || (y += f.vx, n += f.vy, r++);
33
+ return r === 0 ? M() : { x: y / r - o.vx, y: n / r - o.vy };
34
+ }
35
+ function E(o, x, t, y) {
36
+ let n = 0, r = 0, f = 0;
37
+ for (const c of x)
38
+ c === o || (c.x - o.x) ** 2 + (c.y - o.y) ** 2 > t * t || (n += c.x, r += c.y, f++);
39
+ return f === 0 ? M() : b(o, n / f, r / f, y);
40
+ }
41
+ function O(o, x, t, y) {
42
+ const n = Math.floor(o.x / t), r = Math.floor(o.y / t), f = x.stepAt(n, r);
43
+ if (f) return h(f[0], f[1], y, o);
44
+ if (x.costAt(n, r) === 0) return { x: -o.vx, y: -o.vy };
45
+ let c = 1 / 0, v = 0, i = 0;
46
+ for (let s = 1; s <= 2 && c === 1 / 0; s++)
47
+ for (let u = -s; u <= s; u++)
48
+ for (let l = -s; l <= s; l++) {
49
+ if (Math.max(Math.abs(l), Math.abs(u)) !== s) continue;
50
+ const p = x.costAt(n + l, r + u);
51
+ p < c && (c = p, v = l, i = u);
52
+ }
53
+ return c === 1 / 0 ? { x: -o.vx, y: -o.vy } : b(o, (n + v + 0.5) * t, (r + i + 0.5) * t, y);
54
+ }
55
+ function Z(o, ...x) {
56
+ let t = 0, y = 0;
57
+ for (const [r, f] of x)
58
+ t += r.x * f, y += r.y * f;
59
+ const n = Math.hypot(t, y);
60
+ return n > o && (t = t / n * o, y = y / n * o), { x: t, y };
61
+ }
62
+ function j(o, x, t, y) {
63
+ o.vx += x.x * y, o.vy += x.y * y;
64
+ const n = Math.hypot(o.vx, o.vy);
65
+ n > t && (o.vx = o.vx / n * t, o.vy = o.vy / n * t), o.x += o.vx * y, o.y += o.vy * y;
66
+ }
67
+ export {
68
+ k as alignment,
69
+ j as applySteering,
70
+ w as arrive,
71
+ E as cohesion,
72
+ Z as combineSteering,
73
+ I as flee,
74
+ O as followFlow,
75
+ b as seek,
76
+ A as separation
77
+ };
@@ -0,0 +1,96 @@
1
+ import { timeoutSignal as p } from "../platform/timeoutSignal.js";
2
+ class g extends Error {
3
+ constructor(t, e, r, n, u) {
4
+ super(r), this.status = t, this.code = e, this.details = n, this.body = u, this.name = "ApiError";
5
+ }
6
+ status;
7
+ code;
8
+ details;
9
+ body;
10
+ }
11
+ function y(i) {
12
+ if (!i || typeof i != "object") return {};
13
+ const t = i;
14
+ return {
15
+ code: typeof t.code == "string" ? t.code : void 0,
16
+ message: typeof t.message == "string" ? t.message : void 0,
17
+ details: t.details && typeof t.details == "object" ? t.details : void 0
18
+ };
19
+ }
20
+ function v(i) {
21
+ const t = AbortSignal.any;
22
+ if (typeof t == "function") return t.call(AbortSignal, [...i]);
23
+ const e = new AbortController();
24
+ for (const r of i) {
25
+ if (r.aborted) {
26
+ e.abort(r.reason);
27
+ break;
28
+ }
29
+ r.addEventListener("abort", () => e.abort(r.reason), { once: !0 });
30
+ }
31
+ return e.signal;
32
+ }
33
+ class E {
34
+ constructor(t) {
35
+ this.options = t;
36
+ }
37
+ options;
38
+ token = null;
39
+ /** A new access token for a 401 (`RefreshResult`); unset, a 401 is simply thrown. */
40
+ refresher = null;
41
+ /** Called when a 401 ends the session: no refresher, a refused refresh, or a retry refused again. */
42
+ onUnauthorized = null;
43
+ get accessToken() {
44
+ return this.token;
45
+ }
46
+ setToken(t) {
47
+ this.token = t;
48
+ }
49
+ /** Sends a request and returns its parsed JSON body (undefined for an empty or unreadable one). */
50
+ async request(t, e, r, n = {}, u = !1) {
51
+ const o = this.options, l = { Accept: "application/json", ...o.headers?.(), ...n.headers };
52
+ r !== void 0 && (l["Content-Type"] = "application/json");
53
+ const f = this.token;
54
+ f && (l.Authorization = `Bearer ${f}`);
55
+ const w = p(n.timeoutMs ?? o.timeoutMs ?? 1e4), b = n.signal ? v([w, n.signal]) : w;
56
+ let s, h;
57
+ try {
58
+ const a = typeof o.baseUrl == "function" ? o.baseUrl(e) : o.baseUrl;
59
+ s = await (o.fetch ?? fetch)(a + e, {
60
+ method: t,
61
+ headers: l,
62
+ body: r !== void 0 ? JSON.stringify(r) : void 0,
63
+ signal: b
64
+ }), h = s.status === 204 ? "" : await s.text();
65
+ } catch (a) {
66
+ throw n.signal?.aborted ? new g(0, "ABORTED", "Aborted.") : (console.warn("[api] network error", t, e, a), this.networkError());
67
+ }
68
+ let c;
69
+ if (h)
70
+ try {
71
+ c = JSON.parse(h);
72
+ } catch {
73
+ c = void 0;
74
+ }
75
+ if (s.ok) return c;
76
+ const d = (o.describe ?? y)(c, s.status), k = new g(s.status, d.code ?? `HTTP_${s.status}`, d.message ?? `HTTP ${s.status}`, d.details, c);
77
+ if (o.onError?.(k), o.onStatus?.[s.status]?.(k), s.status === 401 && this.token && !u && !o.noRefresh?.(e)) {
78
+ if (f !== this.token) return this.request(t, e, r, n, !0);
79
+ if (this.refresher) {
80
+ const a = await this.refresher().catch(() => null);
81
+ if (a !== null && a !== "refused")
82
+ return this.token = a, this.request(t, e, r, n, !0);
83
+ if (a === null) throw this.networkError();
84
+ }
85
+ }
86
+ throw s.status === 401 && this.token && this.onUnauthorized?.(), k;
87
+ }
88
+ networkError() {
89
+ const t = this.options.networkMessage;
90
+ return new g(0, "NETWORK", typeof t == "function" ? t() : t ?? "Cannot reach the server.");
91
+ }
92
+ }
93
+ export {
94
+ E as ApiClient,
95
+ g as ApiError
96
+ };
@@ -1,55 +1,62 @@
1
1
  class x {
2
- constructor(s = 100, a = 120, t = 30) {
3
- this.delayMs = s, this.maxExtrapolateMs = a, this.keep = t;
2
+ constructor(e = 100, a = 120, t = 30) {
3
+ this.delayMs = e, this.maxExtrapolateMs = a, this.keep = t;
4
4
  }
5
5
  delayMs;
6
6
  maxExtrapolateMs;
7
7
  keep;
8
8
  samples = /* @__PURE__ */ new Map();
9
9
  /** Records every body of a snapshot taken at `time`. */
10
- push(s, a) {
11
- for (const [t, n, o, h, m, p, c] of a) {
10
+ push(e, a) {
11
+ for (const [t, n, r, h, m, p, c] of a) {
12
12
  let i = this.samples.get(t);
13
13
  i || (i = [], this.samples.set(t, i));
14
14
  const l = i[i.length - 1];
15
- l && s <= l.time || (i.push({ time: s, x: n, y: o, aim: h, anim: m, hp: p, flags: c }), i.length > this.keep && i.splice(0, i.length - this.keep));
15
+ l && e <= l.time || (i.push({ time: e, x: n, y: r, aim: h, anim: m, hp: p, flags: c }), i.length > this.keep && i.splice(0, i.length - this.keep));
16
16
  }
17
17
  }
18
+ /**
19
+ * The server time bodies are drawn at when it is `now` (`serverNow()`): what a shot should carry, so a server with
20
+ * lag compensation judges it against the picture the player aimed at.
21
+ */
22
+ viewTime(e) {
23
+ return e - this.delayMs;
24
+ }
18
25
  /** Forgets a body (it left view). */
19
- remove(s) {
20
- this.samples.delete(s);
26
+ remove(e) {
27
+ this.samples.delete(e);
21
28
  }
22
- has(s) {
23
- return this.samples.has(s);
29
+ has(e) {
30
+ return this.samples.has(e);
24
31
  }
25
32
  ids() {
26
33
  return this.samples.keys();
27
34
  }
28
35
  /** Where body `id` should be drawn at server time `now`, or null if nothing is known of it. */
29
- sample(s, a) {
30
- const t = this.samples.get(s);
36
+ sample(e, a) {
37
+ const t = this.samples.get(e);
31
38
  if (!t || t.length === 0) return null;
32
- const n = a - this.delayMs, o = t[0];
33
- if (n <= o.time || t.length === 1) return g(o);
39
+ const n = a - this.delayMs, r = t[0];
40
+ if (n <= r.time || t.length === 1) return g(r);
34
41
  for (let i = t.length - 1; i > 0; i--) {
35
- const l = t[i - 1], r = t[i];
36
- if (n >= l.time && n <= r.time) {
37
- const u = r.time === l.time ? 1 : (n - l.time) / (r.time - l.time);
38
- return f(l, r, u);
42
+ const l = t[i - 1], o = t[i];
43
+ if (n >= l.time && n <= o.time) {
44
+ const u = o.time === l.time ? 1 : (n - l.time) / (o.time - l.time);
45
+ return f(l, o, u);
39
46
  }
40
47
  }
41
48
  const h = t[t.length - 2], m = t[t.length - 1], p = Math.min(n - m.time, this.maxExtrapolateMs), c = m.time === h.time ? 1 : 1 + p / (m.time - h.time);
42
49
  return f(h, m, c);
43
50
  }
44
51
  }
45
- function g(e) {
46
- return { x: e.x, y: e.y, aim: e.aim, anim: e.anim, hp: e.hp, flags: e.flags };
52
+ function g(s) {
53
+ return { x: s.x, y: s.y, aim: s.aim, anim: s.anim, hp: s.hp, flags: s.flags };
47
54
  }
48
- function f(e, s, a) {
49
- let t = s.aim - e.aim;
55
+ function f(s, e, a) {
56
+ let t = e.aim - s.aim;
50
57
  t > Math.PI && (t -= Math.PI * 2), t < -Math.PI && (t += Math.PI * 2);
51
- const n = a < 1 ? e : s;
52
- return { x: e.x + (s.x - e.x) * a, y: e.y + (s.y - e.y) * a, aim: e.aim + t * a, anim: n.anim, hp: n.hp, flags: n.flags };
58
+ const n = a < 1 ? s : e;
59
+ return { x: s.x + (e.x - s.x) * a, y: s.y + (e.y - s.y) * a, aim: s.aim + t * a, anim: n.anim, hp: n.hp, flags: n.flags };
53
60
  }
54
61
  export {
55
62
  x as InterpolationBuffer
@@ -0,0 +1,100 @@
1
+ class k {
2
+ /** `keepMs`: how much history is kept; at least the longest rewind allowed plus a snapshot interval. */
3
+ constructor(s = 1e3) {
4
+ this.keepMs = s;
5
+ }
6
+ keepMs;
7
+ frames = [];
8
+ /** The latest recorded time, or -Infinity before any. */
9
+ get newest() {
10
+ return this.frames.length ? this.frames[this.frames.length - 1].time : -1 / 0;
11
+ }
12
+ get oldest() {
13
+ return this.frames.length ? this.frames[0].time : -1 / 0;
14
+ }
15
+ /** Records every body's position at `time`. A time not after the last one recorded replaces that frame. */
16
+ record(s, t) {
17
+ const e = /* @__PURE__ */ new Map();
18
+ for (const r of t) e.set(r.id, [r.x, r.y]);
19
+ const n = this.frames[this.frames.length - 1];
20
+ n && s <= n.time ? n.pos = e : this.frames.push({ time: s, pos: e });
21
+ const o = s - this.keepMs;
22
+ for (; this.frames.length > 2 && this.frames[1].time <= o; ) this.frames.shift();
23
+ }
24
+ /** Forgets a body everywhere in the history (it left the game, not just the view). */
25
+ forget(s) {
26
+ for (const t of this.frames) t.pos.delete(s);
27
+ }
28
+ clear() {
29
+ this.frames.length = 0;
30
+ }
31
+ /**
32
+ * A time a client claims it saw, kept within `[now - maxRewindMs, now]`: the window a rewind is honoured in. A
33
+ * claim that is not a finite number is taken as `now` (no rewind).
34
+ */
35
+ static clampTime(s, t, e) {
36
+ return typeof s != "number" || !Number.isFinite(s) ? t : Math.min(t, Math.max(t - e, s));
37
+ }
38
+ /**
39
+ * Where body `id` was at `time`, blended between the frames around it as `InterpolationBuffer` blends; null when
40
+ * the history has no frame of it. Before the oldest frame it is where it was then; after the newest, where it is.
41
+ */
42
+ at(s, t) {
43
+ const e = this.around(t);
44
+ return e ? b(e[0], e[1], e[2], s) : null;
45
+ }
46
+ /** Every body in the history at `time`. */
47
+ all(s) {
48
+ const t = this.around(s);
49
+ if (!t) return [];
50
+ const [e, n, o] = t, r = /* @__PURE__ */ new Set([...e.pos.keys(), ...n.pos.keys()]), i = [];
51
+ for (const a of r) {
52
+ const h = b(e, n, o, a);
53
+ i.push({ id: a, x: h.x, y: h.y });
54
+ }
55
+ return i;
56
+ }
57
+ /** The bodies whose centre was within `radius` of (x, y) at `time`, nearest first; `except` (the shooter) left out. */
58
+ near(s, t, e, n, o) {
59
+ return this.all(s).filter((i) => i.id !== o && (i.x - t) ** 2 + (i.y - e) ** 2 <= n * n).sort((i, a) => (i.x - t) ** 2 + (i.y - e) ** 2 - ((a.x - t) ** 2 + (a.y - e) ** 2));
60
+ }
61
+ /**
62
+ * A hitscan at `time`: the bodies a ray from (x, y) along (dx, dy) passed within `radius` of, before `range` px, in
63
+ * the order it met them. `except` (the shooter) is left out. Walls are the game's to check against the first hit.
64
+ */
65
+ alongRay(s, t, e, n, o, r, i, a) {
66
+ const h = Math.hypot(n, o);
67
+ if (h === 0) return [];
68
+ const u = n / h, m = o / h, p = [];
69
+ for (const f of this.all(s)) {
70
+ if (f.id === a) continue;
71
+ const c = (f.x - t) * u + (f.y - e) * m, g = t + u * c - f.x, y = e + m * c - f.y, x = g * g + y * y;
72
+ if (x > i * i) continue;
73
+ const M = c - Math.sqrt(i * i - x);
74
+ c < -i || M > r || p.push({ id: f.id, x: f.x, y: f.y, along: Math.max(0, M) });
75
+ }
76
+ return p.sort((f, c) => f.along - c.along);
77
+ }
78
+ /** The two frames around `time` and how far between them it is (0 at the first, 1 at the second). */
79
+ around(s) {
80
+ const t = this.frames;
81
+ if (t.length === 0) return null;
82
+ if (s <= t[0].time) return [t[0], t[0], 0];
83
+ const e = t[t.length - 1];
84
+ if (s >= e.time) return [e, e, 0];
85
+ for (let n = t.length - 1; n > 0; n--) {
86
+ const o = t[n - 1], r = t[n];
87
+ if (s >= o.time && s <= r.time) return [o, r, r.time === o.time ? 1 : (s - o.time) / (r.time - o.time)];
88
+ }
89
+ return null;
90
+ }
91
+ }
92
+ function b(l, s, t, e) {
93
+ const n = l.pos.get(e), o = s.pos.get(e);
94
+ if (n && o) return { x: n[0] + (o[0] - n[0]) * t, y: n[1] + (o[1] - n[1]) * t };
95
+ const r = n ?? o;
96
+ return r ? { x: r[0], y: r[1] } : null;
97
+ }
98
+ export {
99
+ k as LagCompensator
100
+ };