@arcadible/sdk 1.3.0 → 1.4.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/README.md +21 -10
- package/dist/bus/protocol.js +5 -5
- package/dist/client.d.ts +6 -5
- package/dist/client.js +4 -4
- package/dist/lifecycle/client.d.ts +2 -2
- package/dist/lifecycle/client.js +37 -33
- package/dist/lifecycle/rules.d.ts +4 -4
- package/dist/lifecycle/rules.js +15 -15
- package/dist/lifecycle/server.d.ts +3 -3
- package/dist/lifecycle/server.js +8 -7
- package/dist/saves/rules.js +4 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
<h1 align="center">Arcadible SDK</h1>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
|
-
|
|
10
|
+
Arcadible's loading screen for your game, and saves that carry over from one version to the next.
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
14
|
<a href="https://developer.arcadible.com/references/arcadible-sdk">Docs</a> ·
|
|
15
|
+
<a href="https://developer.arcadible.com/build/initialization">Initialization</a> ·
|
|
15
16
|
<a href="https://developer.arcadible.com/build/saves">Saves</a> ·
|
|
16
17
|
<a href="https://arcadible.com">Arcadible</a> ·
|
|
17
18
|
<a href="https://studio.arcadible.com">Studio</a>
|
|
@@ -19,7 +20,7 @@
|
|
|
19
20
|
|
|
20
21
|
<br>
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
The Arcadible SDK is optional: a game runs on [Arcadible](https://arcadible.com) without it. With it, a game gets two things from the play page around it: its [initialization](https://developer.arcadible.com/build/initialization), bracketed, so Arcadible's loading screen shows the game's splash and progress until its first frame is drawn, and [saves](https://developer.arcadible.com/build/saves), kept by the play page, so the player's progress carries over from one version to the next.
|
|
23
24
|
|
|
24
25
|
## Install
|
|
25
26
|
|
|
@@ -29,29 +30,39 @@ npm install @arcadible/sdk
|
|
|
29
30
|
|
|
30
31
|
The package is for a game with a build step, such as a Vite project. A game without one uses the [hosted script](https://developer.arcadible.com/references/arcadible-sdk#install) instead.
|
|
31
32
|
|
|
32
|
-
##
|
|
33
|
+
## Initialization
|
|
33
34
|
|
|
34
35
|
```js
|
|
35
36
|
import { arcadible } from "@arcadible/sdk";
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
await arcadible.initStart(); // first thing in your game's code
|
|
39
|
+
arcadible.initProgress(0.5);
|
|
40
|
+
// … load, build the scene, and draw the first frame …
|
|
41
|
+
await arcadible.initComplete();
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Call `initStart()` first thing in your game's code, report how far along you are with `initProgress()`, from 0 to 1, if you can measure it, and call `initComplete()` once your first frame is drawn. Arcadible shows your splash and the progress until then, and `initComplete()` resolves once the loading screen has faded into your game.
|
|
45
|
+
|
|
46
|
+
## Save and load
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// once the saves have loaded
|
|
39
50
|
const saved = await arcadible.saves.read("progress");
|
|
40
51
|
const progress = saved ? JSON.parse(saved) : { level: 1 };
|
|
41
52
|
|
|
42
|
-
// at a checkpoint
|
|
53
|
+
// at a checkpoint
|
|
43
54
|
await arcadible.saves.write("progress", JSON.stringify(progress));
|
|
44
55
|
```
|
|
45
56
|
|
|
46
|
-
A save is a name holding one string. `
|
|
57
|
+
A save is a name holding one string. Once `initStart()` has resolved, `readSync`, `listSync`, and `infoSync` answer at once from memory, for reads during play. Every call that fails rejects (or, for the sync calls, throws) with an `ArcadibleError`, whose `code` says what to do. `arcadible.saves.where` says who can read the saves back: every version of the game, only this build, or only until the page closes.
|
|
47
58
|
|
|
48
|
-
Off Arcadible, such as on your dev server, the package works
|
|
59
|
+
Off Arcadible, such as on your dev server, the package still works, with the same rules and limits: there's no loading screen, so `initComplete()` resolves at once, saves are kept in the game's own browser storage, `arcadible.saves.where` is `"build"`, and `arcadible.build` is `null`.
|
|
49
60
|
|
|
50
61
|
## Learn more
|
|
51
62
|
|
|
52
|
-
- [
|
|
53
|
-
- [`arcadible.saves`](https://developer.arcadible.com/references/arcadible-sdk/saves): every call, what it returns, and when it fails.
|
|
63
|
+
- [Initialization](https://developer.arcadible.com/build/initialization): where each call goes, progress, and what comes after.
|
|
54
64
|
- [Saves](https://developer.arcadible.com/build/saves): using saves well, across versions, channels, and tabs, and where they're kept.
|
|
65
|
+
- [Arcadible SDK](https://developer.arcadible.com/references/arcadible-sdk): including it, every call, the saves' included, and every code.
|
|
55
66
|
- [Limits](https://developer.arcadible.com/references/limits#saves): how many saves, and how large.
|
|
56
67
|
|
|
57
68
|
## License
|
package/dist/bus/protocol.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// The bus's rules, shared by both ends so they can't drift apart: the
|
|
2
2
|
// handshake, the message shapes, the error codes, and the limits on what
|
|
3
|
-
// crosses it
|
|
3
|
+
// crosses it. It knows nothing of any module.
|
|
4
4
|
// [declare]
|
|
5
5
|
// The bus's own version: the handshake and the message shapes. New modules,
|
|
6
6
|
// names, and fields are additions within it.
|
|
@@ -15,9 +15,9 @@ export const REQUEST_TIMEOUT = 10_000;
|
|
|
15
15
|
// included, whatever framed it. Who may frame a build is decided outside the
|
|
16
16
|
// game, where it can change: on Arcadible by each build's `frame-ancestors`,
|
|
17
17
|
// which the browser enforces before the game runs, and elsewhere by whoever
|
|
18
|
-
// serves it. So the host is never trusted with anything of value
|
|
19
|
-
//
|
|
20
|
-
//
|
|
18
|
+
// serves it. So the host is never trusted with anything of value. Only
|
|
19
|
+
// `null` is refused: a `file://` page or a sandboxed frame, which can't be
|
|
20
|
+
// told apart.
|
|
21
21
|
export function isHostOrigin(origin, origins) {
|
|
22
22
|
return origins
|
|
23
23
|
? origins.includes(origin)
|
|
@@ -29,7 +29,7 @@ export const MAX_IN_FLIGHT = 64;
|
|
|
29
29
|
// The largest message either side sends: room for a whole 1 MB save, or
|
|
30
30
|
// every save at once (a game's are 1 MB together), and the rest of the
|
|
31
31
|
// message. The page refuses a larger request, and never sends a larger
|
|
32
|
-
// answer or event
|
|
32
|
+
// answer or event.
|
|
33
33
|
export const MAX_MESSAGE = 1024 * 1024 + 64 * 1024;
|
|
34
34
|
// [declare]
|
|
35
35
|
// Every code a call can fail with. Worth retrying: `busy`, `timeout`, and
|
package/dist/client.d.ts
CHANGED
|
@@ -24,22 +24,23 @@ export interface Arcadible {
|
|
|
24
24
|
/** Saves that carry over between the game's versions. */
|
|
25
25
|
readonly saves: Saves;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
* await, and Arcadible shows the game's loading screen until
|
|
27
|
+
* Starts the game's initialization: call it first, before anything you
|
|
28
|
+
* await, and Arcadible shows the game's loading screen until
|
|
29
|
+
* `initComplete()`.
|
|
29
30
|
* It resolves as `ready` does, once the SDK and the saves are ready.
|
|
30
31
|
*/
|
|
31
|
-
|
|
32
|
+
initStart(): Promise<Ready>;
|
|
32
33
|
/**
|
|
33
34
|
* How far along the initialization is, from 0 to 1, measured however the
|
|
34
35
|
* game likes. Optional; a lower value than the last is ignored.
|
|
35
36
|
*/
|
|
36
37
|
initProgress(fraction: number): void;
|
|
37
38
|
/**
|
|
38
|
-
*
|
|
39
|
+
* Completes the initialization, once the game's first frame is drawn:
|
|
39
40
|
* Arcadible takes its loading screen down, and this resolves once the
|
|
40
41
|
* game is visible.
|
|
41
42
|
*/
|
|
42
|
-
|
|
43
|
+
initComplete(): Promise<void>;
|
|
43
44
|
}
|
|
44
45
|
export type ClientOptions = {
|
|
45
46
|
window?: Window;
|
package/dist/client.js
CHANGED
|
@@ -47,15 +47,15 @@ export function createClient(options = {}) {
|
|
|
47
47
|
return settled ? settled.build : undefined;
|
|
48
48
|
},
|
|
49
49
|
saves,
|
|
50
|
-
|
|
51
|
-
lifecycle.
|
|
50
|
+
initStart() {
|
|
51
|
+
lifecycle.start();
|
|
52
52
|
return ready;
|
|
53
53
|
},
|
|
54
54
|
initProgress(fraction) {
|
|
55
55
|
lifecycle.progress(fraction);
|
|
56
56
|
},
|
|
57
|
-
|
|
58
|
-
return lifecycle.
|
|
57
|
+
initComplete() {
|
|
58
|
+
return lifecycle.complete();
|
|
59
59
|
},
|
|
60
60
|
};
|
|
61
61
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Bus } from "../bus/client.js";
|
|
2
2
|
export type Lifecycle = {
|
|
3
|
-
|
|
3
|
+
start(): void;
|
|
4
4
|
progress(fraction: unknown): void;
|
|
5
|
-
|
|
5
|
+
complete(): Promise<void>;
|
|
6
6
|
};
|
|
7
7
|
export declare function createLifecycle(bus: Bus, win: Window | undefined): Lifecycle;
|
package/dist/lifecycle/client.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
// The game's side of its initialization: `
|
|
2
|
-
// `
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// The game's side of its initialization: `initStart`, `initProgress`, and
|
|
2
|
+
// `initComplete` on `arcadible`. The page keeps its loading screen only for
|
|
3
|
+
// a game that started before its own `load`, which this side reports, once,
|
|
4
|
+
// as it happens, so the page decides without a timer. Calls after that do
|
|
5
|
+
// nothing, and the console says why once.
|
|
6
6
|
import { isObject, log } from "../bus/protocol.js";
|
|
7
|
-
import {
|
|
7
|
+
import { COMPLETE_TIMEOUT, fractionOf, Names } from "./rules.js";
|
|
8
8
|
// [function]
|
|
9
9
|
export function createLifecycle(bus, win) {
|
|
10
|
-
//
|
|
11
|
-
// keep. `false` once `load` passed without a
|
|
12
|
-
let
|
|
10
|
+
// started before the game's `load`: the loading screen is the page's to
|
|
11
|
+
// keep. `false` once `load` passed without a start.
|
|
12
|
+
let started = null;
|
|
13
13
|
let loaded = false;
|
|
14
14
|
let last = -1;
|
|
15
|
-
let
|
|
15
|
+
let completed = null;
|
|
16
16
|
let warnedLate = false;
|
|
17
17
|
let warnedValue = false;
|
|
18
18
|
const framed = Boolean(win && win.parent !== win);
|
|
@@ -20,33 +20,33 @@ export function createLifecycle(bus, win) {
|
|
|
20
20
|
if (warnedLate || !framed)
|
|
21
21
|
return;
|
|
22
22
|
warnedLate = true;
|
|
23
|
-
log("warn", `${call} came after the page loaded, so Arcadible's loading screen was already down. Call
|
|
23
|
+
log("warn", `${call} came after the page loaded, so Arcadible's loading screen was already down. Call initStart() as your code starts, before anything you await or schedule for later.`);
|
|
24
24
|
};
|
|
25
25
|
const onLoad = function () {
|
|
26
26
|
if (loaded)
|
|
27
27
|
return;
|
|
28
28
|
loaded = true;
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
bus.emit(Names.Loaded, {
|
|
29
|
+
if (started === null)
|
|
30
|
+
started = false;
|
|
31
|
+
bus.emit(Names.Loaded, { started });
|
|
32
32
|
};
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
if (!
|
|
33
|
+
const start = function (call) {
|
|
34
|
+
if (started !== null) {
|
|
35
|
+
if (!started)
|
|
36
36
|
late(call);
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
if (loaded) {
|
|
40
|
-
|
|
40
|
+
started = false;
|
|
41
41
|
late(call);
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
bus.emit(Names.
|
|
44
|
+
started = true;
|
|
45
|
+
bus.emit(Names.Start);
|
|
46
46
|
};
|
|
47
47
|
// [start]
|
|
48
|
-
// the game's own `load` is the frame's on the page: a game that
|
|
49
|
-
// then keeps the loading screen. A script that runs after it (added by
|
|
48
|
+
// the game's own `load` is the frame's on the page: a game that started
|
|
49
|
+
// by then keeps the loading screen. A script that runs after it (added by
|
|
50
50
|
// code, late) reports at once.
|
|
51
51
|
if (win && typeof win.addEventListener === "function") {
|
|
52
52
|
if (win.document?.readyState === "complete")
|
|
@@ -55,8 +55,8 @@ export function createLifecycle(bus, win) {
|
|
|
55
55
|
win.addEventListener("load", onLoad, { once: true });
|
|
56
56
|
}
|
|
57
57
|
return {
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
start() {
|
|
59
|
+
start("initStart");
|
|
60
60
|
},
|
|
61
61
|
progress(fraction) {
|
|
62
62
|
const value = fractionOf(fraction);
|
|
@@ -67,22 +67,26 @@ export function createLifecycle(bus, win) {
|
|
|
67
67
|
}
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
|
-
|
|
71
|
-
if (!
|
|
70
|
+
start("initProgress");
|
|
71
|
+
if (!started || completed || value <= last)
|
|
72
72
|
return;
|
|
73
73
|
last = value;
|
|
74
74
|
bus.emit(Names.Progress, { fraction: value });
|
|
75
75
|
},
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
return
|
|
79
|
-
|
|
76
|
+
complete() {
|
|
77
|
+
if (completed)
|
|
78
|
+
return completed;
|
|
79
|
+
start("initComplete");
|
|
80
80
|
// a page without a loading screen, an older one, or none standing
|
|
81
81
|
// alone, answers `unsupported`: the game is visible already.
|
|
82
|
-
|
|
83
|
-
? bus
|
|
82
|
+
completed = started
|
|
83
|
+
? bus
|
|
84
|
+
.request(Names.Complete, {}, isObject, {
|
|
85
|
+
timeout: COMPLETE_TIMEOUT,
|
|
86
|
+
})
|
|
87
|
+
.then(() => undefined, () => undefined)
|
|
84
88
|
: Promise.resolve();
|
|
85
|
-
return
|
|
89
|
+
return completed;
|
|
86
90
|
},
|
|
87
91
|
};
|
|
88
92
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export declare const Names: {
|
|
2
|
-
readonly
|
|
2
|
+
readonly Start: "lifecycle.initStart";
|
|
3
3
|
readonly Progress: "lifecycle.initProgress";
|
|
4
4
|
readonly Loaded: "lifecycle.loaded";
|
|
5
|
-
readonly
|
|
5
|
+
readonly Complete: "lifecycle.initComplete";
|
|
6
6
|
};
|
|
7
|
-
export declare const INIT_SINCE = "1.
|
|
8
|
-
export declare const
|
|
7
|
+
export declare const INIT_SINCE = "1.4.0";
|
|
8
|
+
export declare const COMPLETE_TIMEOUT = 60000;
|
|
9
9
|
export declare function reportsInit(client: unknown): boolean;
|
|
10
10
|
export declare function fractionOf(value: unknown): number | null;
|
package/dist/lifecycle/rules.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
// The game's initialization on the bus, shared by both ends: the messages'
|
|
2
|
-
// names, and the first SDK that sends them
|
|
3
|
-
//
|
|
4
|
-
// `arcadible` itself.
|
|
2
|
+
// names, and the first SDK that sends them. On the bus they're
|
|
3
|
+
// `lifecycle`'s; games call them on `arcadible` itself.
|
|
5
4
|
// [declare]
|
|
6
5
|
export const Names = {
|
|
7
|
-
// the game
|
|
8
|
-
|
|
6
|
+
// the game started its initialization: an event.
|
|
7
|
+
Start: "lifecycle.initStart",
|
|
9
8
|
// how far along it is, `{ fraction }`, from 0 to 1: an event.
|
|
10
9
|
Progress: "lifecycle.initProgress",
|
|
11
|
-
// the game's own `load`, `{
|
|
10
|
+
// the game's own `load`, `{ started }`: whether it started before it. An
|
|
12
11
|
// event, sent once, so the page decides without a timer.
|
|
13
12
|
Loaded: "lifecycle.loaded",
|
|
14
13
|
// its first frame is drawn: a request, answered once the game is visible.
|
|
15
|
-
|
|
14
|
+
Complete: "lifecycle.initComplete",
|
|
16
15
|
};
|
|
17
|
-
// The first SDK that sends them. An older one
|
|
18
|
-
// loading screen down at `load`, without waiting to hear.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
|
|
16
|
+
// The first SDK that sends them. An older one doesn't, so the page takes its
|
|
17
|
+
// loading screen down at `load`, without waiting to hear. 1.3's SDKs sent
|
|
18
|
+
// these under other names, so the page treats them as older too.
|
|
19
|
+
export const INIT_SINCE = "1.4.0";
|
|
20
|
+
// How long `initComplete()` waits for the page to say the game is visible:
|
|
21
|
+
// past the loading screen's minimum and fade, and a device held the wrong
|
|
22
|
+
// way for a while. Past it, the game goes on as if visible.
|
|
23
|
+
export const COMPLETE_TIMEOUT = 60_000;
|
|
24
24
|
// [function]
|
|
25
|
-
// a version's numbers, `1.
|
|
25
|
+
// a version's numbers, `1.4.0-beta.1` as [1, 4, 0], or null.
|
|
26
26
|
function numbers(version) {
|
|
27
27
|
const match = /^(\d+)\.(\d+)\.(\d+)/u.exec(version);
|
|
28
28
|
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Module } from "../bus/server.js";
|
|
2
2
|
export type LifecycleHost = {
|
|
3
|
-
|
|
3
|
+
start(): void;
|
|
4
4
|
progress(fraction: number): void;
|
|
5
|
-
loaded(
|
|
6
|
-
|
|
5
|
+
loaded(started: boolean): void;
|
|
6
|
+
complete(): Promise<void>;
|
|
7
7
|
};
|
|
8
8
|
export declare function lifecycleServer(host: LifecycleHost): () => Module;
|
package/dist/lifecycle/server.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// The page's side of the game's initialization: it passes what the game
|
|
2
|
-
// reports to the page's loading screen, and answers `
|
|
3
|
-
// says the game is visible. A page without a loading screen leaves it
|
|
4
|
-
// so `
|
|
2
|
+
// reports to the page's loading screen, and answers `initComplete` once the
|
|
3
|
+
// page says the game is visible. A page without a loading screen leaves it
|
|
4
|
+
// out, so `initComplete` gets `unsupported`, which a game takes as visible
|
|
5
|
+
// at once.
|
|
5
6
|
// [import]
|
|
6
7
|
import { isObject } from "../bus/protocol.js";
|
|
7
8
|
import { fractionOf, Names } from "./rules.js";
|
|
@@ -9,23 +10,23 @@ import { fractionOf, Names } from "./rules.js";
|
|
|
9
10
|
export function lifecycleServer(host) {
|
|
10
11
|
return () => ({
|
|
11
12
|
handlers: {
|
|
12
|
-
[Names.
|
|
13
|
+
[Names.Complete]: {
|
|
13
14
|
parallel: true,
|
|
14
15
|
run: async () => {
|
|
15
|
-
await host.
|
|
16
|
+
await host.complete();
|
|
16
17
|
return {};
|
|
17
18
|
},
|
|
18
19
|
},
|
|
19
20
|
},
|
|
20
21
|
events: {
|
|
21
|
-
[Names.
|
|
22
|
+
[Names.Start]: () => host.start(),
|
|
22
23
|
[Names.Progress]: (data) => {
|
|
23
24
|
const fraction = isObject(data) ? fractionOf(data["fraction"]) : null;
|
|
24
25
|
if (fraction !== null)
|
|
25
26
|
host.progress(fraction);
|
|
26
27
|
},
|
|
27
28
|
[Names.Loaded]: (data) => {
|
|
28
|
-
host.loaded(isObject(data) && data["
|
|
29
|
+
host.loaded(isObject(data) && data["started"] === true);
|
|
29
30
|
},
|
|
30
31
|
},
|
|
31
32
|
});
|
package/dist/saves/rules.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Saves' rules, shared by the game's side and the page's so they can't drift
|
|
2
|
-
// apart: the shapes, the limits, and their checks
|
|
2
|
+
// apart: the shapes, the limits, and their checks.
|
|
3
3
|
// [import]
|
|
4
4
|
import { ArcadibleError, Codes, isNumber, isObject, isStringOrNull, utf8Size, } from "../bus/protocol.js";
|
|
5
5
|
// [declare]
|
|
6
|
-
// Saves' limits, the same everywhere
|
|
6
|
+
// Saves' limits, the same everywhere.
|
|
7
7
|
export const MAX_SAVES = 32;
|
|
8
8
|
// Every save's document together, in UTF-8 bytes.
|
|
9
9
|
export const MAX_TOTAL = 1024 * 1024;
|
|
@@ -48,8 +48,8 @@ export function checkWrite(saves, name, data) {
|
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
50
|
// [function]
|
|
51
|
-
// What the page sends of a save, checked for only what a game relies on
|
|
52
|
-
//
|
|
51
|
+
// What the page sends of a save, checked for only what a game relies on,
|
|
52
|
+
// since the host is never trusted: extra fields pass.
|
|
53
53
|
export function isSaveMeta(value) {
|
|
54
54
|
return (isObject(value) &&
|
|
55
55
|
isStringOrNull(value["version"]) &&
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.
|
|
1
|
+
export declare const VERSION = "1.4.0";
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Offst, Inc.",
|
|
3
|
-
"description": "The Arcadible SDK: saves that carry over between
|
|
3
|
+
"description": "The Arcadible SDK: Arcadible's loading screen for a game's initialization, and saves that carry over between its versions.",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@playwright/test": "1.63.0",
|
|
6
6
|
"@types/node": "^25.0.3",
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
],
|
|
44
44
|
"type": "module",
|
|
45
45
|
"types": "./dist/index.d.ts",
|
|
46
|
-
"version": "1.
|
|
46
|
+
"version": "1.4.0"
|
|
47
47
|
}
|