@oasiz/sdk 1.8.4 → 1.8.6
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 +43 -0
- package/dist/index.cjs +287 -64
- package/dist/index.d.cts +30 -3
- package/dist/index.d.ts +30 -3
- package/dist/index.js +285 -64
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -167,6 +167,49 @@ or `southwest`.
|
|
|
167
167
|
`backflip` is not directional, so `getJibbleAnimationId("backflip", "left")`
|
|
168
168
|
still returns `backflip`.
|
|
169
169
|
|
|
170
|
+
#### Local browser sample atlas
|
|
171
|
+
|
|
172
|
+
Inside the Oasiz app, `oasiz.getPlayerCharacter()` returns the authenticated
|
|
173
|
+
player's real character atlas. On `localhost` or `file://` without the app
|
|
174
|
+
bridge, it first fetches an Oasiz-owned real sample atlas from
|
|
175
|
+
`https://api.oasiz.ai/api/sdk/sample-character`, so browser games can test
|
|
176
|
+
sprite loading, atlas slicing, and animation lookup before publishing.
|
|
177
|
+
|
|
178
|
+
The platform sample is generated by the same backend/R2 atlas pipeline as real
|
|
179
|
+
characters, but it is not a user character and it does not expose user id,
|
|
180
|
+
layer config, or personal data. If the endpoint is unavailable, the SDK uses a
|
|
181
|
+
tiny generated atlas as a resilience fallback unless disabled.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const character = await oasiz.getPlayerCharacter();
|
|
185
|
+
|
|
186
|
+
// In Oasiz app: the real signed-in player's character.
|
|
187
|
+
// On localhost without the app bridge: "Oasiz Sample Jibble".
|
|
188
|
+
// On non-local pages without the app bridge: null.
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Use the options when you need explicit behavior:
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
// Keep the old "missing bridge means null" behavior.
|
|
195
|
+
const characterOrNull = await oasiz.getPlayerCharacter({ localFallback: false });
|
|
196
|
+
|
|
197
|
+
// Force the sample atlas in a browser test harness.
|
|
198
|
+
const sampleCharacter = await oasiz.getPlayerCharacter({ localFallback: true });
|
|
199
|
+
|
|
200
|
+
// Strict mode: require the platform-generated sample, with no generated backup.
|
|
201
|
+
const platformOnlySample = await oasiz.getPlayerCharacter({
|
|
202
|
+
localFallback: true,
|
|
203
|
+
generatedFallback: false,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Override the sample endpoint when testing against staging.
|
|
207
|
+
const stagingSample = await oasiz.getPlayerCharacter({
|
|
208
|
+
localFallback: true,
|
|
209
|
+
sampleCharacterUrl: "https://staging-api.oasiz.ai/api/sdk/sample-character",
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
170
213
|
#### HTML5 / TypeScript
|
|
171
214
|
|
|
172
215
|
```ts
|
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,8 @@ __export(index_exports, {
|
|
|
37
37
|
getPlayerName: () => getPlayerName,
|
|
38
38
|
getRoomCode: () => getRoomCode,
|
|
39
39
|
getSafeAreaTop: () => getSafeAreaTop,
|
|
40
|
+
getSamplePlayerCharacter: () => getSamplePlayerCharacter,
|
|
41
|
+
getSampleTextureAtlas: () => getSampleTextureAtlas,
|
|
40
42
|
getViewportInsets: () => getViewportInsets,
|
|
41
43
|
leaveGame: () => leaveGame,
|
|
42
44
|
loadGameState: () => loadGameState,
|
|
@@ -1444,65 +1446,6 @@ function enableAppSimulator(options = {}) {
|
|
|
1444
1446
|
return handle;
|
|
1445
1447
|
}
|
|
1446
1448
|
|
|
1447
|
-
// src/character.ts
|
|
1448
|
-
function isDevelopment2() {
|
|
1449
|
-
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1450
|
-
return nodeEnv !== "production";
|
|
1451
|
-
}
|
|
1452
|
-
function getBridgeWindow2() {
|
|
1453
|
-
if (typeof window === "undefined") {
|
|
1454
|
-
return void 0;
|
|
1455
|
-
}
|
|
1456
|
-
return window;
|
|
1457
|
-
}
|
|
1458
|
-
function warnMissingBridge2(methodName) {
|
|
1459
|
-
if (isDevelopment2()) {
|
|
1460
|
-
console.warn(
|
|
1461
|
-
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1462
|
-
);
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
async function getPlayerCharacter() {
|
|
1466
|
-
const bridge = getBridgeWindow2();
|
|
1467
|
-
if (typeof bridge?.__oasizGetPlayerCharacter !== "function") {
|
|
1468
|
-
warnMissingBridge2("getPlayerCharacter");
|
|
1469
|
-
return null;
|
|
1470
|
-
}
|
|
1471
|
-
try {
|
|
1472
|
-
const result = await bridge.__oasizGetPlayerCharacter();
|
|
1473
|
-
return result ?? null;
|
|
1474
|
-
} catch (error) {
|
|
1475
|
-
if (isDevelopment2()) {
|
|
1476
|
-
console.error("[oasiz/sdk] getPlayerCharacter failed:", error);
|
|
1477
|
-
}
|
|
1478
|
-
return null;
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
|
-
// src/haptics.ts
|
|
1483
|
-
function isDevelopment3() {
|
|
1484
|
-
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1485
|
-
return nodeEnv !== "production";
|
|
1486
|
-
}
|
|
1487
|
-
function getBridgeWindow3() {
|
|
1488
|
-
if (typeof window === "undefined") {
|
|
1489
|
-
return void 0;
|
|
1490
|
-
}
|
|
1491
|
-
return window;
|
|
1492
|
-
}
|
|
1493
|
-
function triggerHaptic(type) {
|
|
1494
|
-
const bridge = getBridgeWindow3();
|
|
1495
|
-
if (typeof bridge?.triggerHaptic === "function") {
|
|
1496
|
-
bridge.triggerHaptic(type);
|
|
1497
|
-
return;
|
|
1498
|
-
}
|
|
1499
|
-
if (isDevelopment3()) {
|
|
1500
|
-
console.warn(
|
|
1501
|
-
"[oasiz/sdk] triggerHaptic bridge is unavailable. This is expected in local development."
|
|
1502
|
-
);
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
|
|
1506
1449
|
// src/jibble.ts
|
|
1507
1450
|
var JIBBLE_DIRECTIONS = [
|
|
1508
1451
|
"n",
|
|
@@ -1603,6 +1546,282 @@ function getJibbleAnimationId(action, direction = "front") {
|
|
|
1603
1546
|
return `${action}_${normalizeJibbleDirection(direction)}`;
|
|
1604
1547
|
}
|
|
1605
1548
|
|
|
1549
|
+
// src/sample-character.ts
|
|
1550
|
+
var FRAME_SIZE = 32;
|
|
1551
|
+
var COLUMNS = 8;
|
|
1552
|
+
var WALK_FRAME_COUNT = 2;
|
|
1553
|
+
var BACKFLIP_FRAME_COUNT = 4;
|
|
1554
|
+
var COLORS = [
|
|
1555
|
+
"#2563eb",
|
|
1556
|
+
"#7c3aed",
|
|
1557
|
+
"#db2777",
|
|
1558
|
+
"#ea580c",
|
|
1559
|
+
"#16a34a",
|
|
1560
|
+
"#0891b2",
|
|
1561
|
+
"#4f46e5",
|
|
1562
|
+
"#be123c"
|
|
1563
|
+
];
|
|
1564
|
+
var IDLE_FRAME_NAMES = JIBBLE_DIRECTIONS.map((direction) => `idle_${direction}`);
|
|
1565
|
+
var WALK_FRAME_NAMES = JIBBLE_DIRECTIONS.flatMap(
|
|
1566
|
+
(direction) => Array.from({ length: WALK_FRAME_COUNT }, (_, index) => `walk_${direction}_${index}`)
|
|
1567
|
+
);
|
|
1568
|
+
var BACKFLIP_FRAME_NAMES = Array.from(
|
|
1569
|
+
{ length: BACKFLIP_FRAME_COUNT },
|
|
1570
|
+
(_, index) => `backflip_${index}`
|
|
1571
|
+
);
|
|
1572
|
+
var SAMPLE_FRAME_NAMES = [
|
|
1573
|
+
...IDLE_FRAME_NAMES,
|
|
1574
|
+
...WALK_FRAME_NAMES,
|
|
1575
|
+
...BACKFLIP_FRAME_NAMES
|
|
1576
|
+
];
|
|
1577
|
+
var IMAGE_WIDTH = COLUMNS * FRAME_SIZE;
|
|
1578
|
+
var IMAGE_HEIGHT = Math.ceil(SAMPLE_FRAME_NAMES.length / COLUMNS) * FRAME_SIZE;
|
|
1579
|
+
function getFrameRect(index) {
|
|
1580
|
+
return {
|
|
1581
|
+
x: index % COLUMNS * FRAME_SIZE,
|
|
1582
|
+
y: Math.floor(index / COLUMNS) * FRAME_SIZE,
|
|
1583
|
+
width: FRAME_SIZE,
|
|
1584
|
+
height: FRAME_SIZE
|
|
1585
|
+
};
|
|
1586
|
+
}
|
|
1587
|
+
function createFrame(name, index) {
|
|
1588
|
+
return {
|
|
1589
|
+
name,
|
|
1590
|
+
...getFrameRect(index)
|
|
1591
|
+
};
|
|
1592
|
+
}
|
|
1593
|
+
function getFrameLabel(name) {
|
|
1594
|
+
return name.replace(/^idle_/, "i ").replace(/^walk_/, "w ").replace(/^backflip_/, "flip ");
|
|
1595
|
+
}
|
|
1596
|
+
function createSvgDataUrl() {
|
|
1597
|
+
const cells = SAMPLE_FRAME_NAMES.map((name, index) => {
|
|
1598
|
+
const { x, y } = getFrameRect(index);
|
|
1599
|
+
const color = COLORS[index % COLORS.length];
|
|
1600
|
+
const label = getFrameLabel(name);
|
|
1601
|
+
return [
|
|
1602
|
+
`<rect x="${x}" y="${y}" width="${FRAME_SIZE}" height="${FRAME_SIZE}" fill="${color}"/>`,
|
|
1603
|
+
`<rect x="${x + 1}" y="${y + 1}" width="${FRAME_SIZE - 2}" height="${FRAME_SIZE - 2}" fill="none" stroke="#ffffff" stroke-opacity="0.35"/>`,
|
|
1604
|
+
`<circle cx="${x + 16}" cy="${y + 11}" r="5" fill="#ffffff" fill-opacity="0.92"/>`,
|
|
1605
|
+
`<rect x="${x + 12}" y="${y + 17}" width="8" height="7" rx="2" fill="#ffffff" fill-opacity="0.86"/>`,
|
|
1606
|
+
`<text x="${x + 16}" y="${y + 30}" text-anchor="middle" font-family="monospace" font-size="5" fill="#ffffff">${label}</text>`
|
|
1607
|
+
].join("");
|
|
1608
|
+
}).join("");
|
|
1609
|
+
const svg = [
|
|
1610
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${IMAGE_WIDTH}" height="${IMAGE_HEIGHT}" viewBox="0 0 ${IMAGE_WIDTH} ${IMAGE_HEIGHT}">`,
|
|
1611
|
+
`<rect width="${IMAGE_WIDTH}" height="${IMAGE_HEIGHT}" fill="#111827"/>`,
|
|
1612
|
+
cells,
|
|
1613
|
+
"</svg>"
|
|
1614
|
+
].join("");
|
|
1615
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
1616
|
+
}
|
|
1617
|
+
function createDirectionalAnimation(animationId, role, direction, frames, frameRate) {
|
|
1618
|
+
return {
|
|
1619
|
+
animationId,
|
|
1620
|
+
role,
|
|
1621
|
+
group: "jibble",
|
|
1622
|
+
direction,
|
|
1623
|
+
frameRate,
|
|
1624
|
+
frames,
|
|
1625
|
+
facingFrameMap: null
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
var SAMPLE_TEXTURE_ATLAS = {
|
|
1629
|
+
imageUrl: createSvgDataUrl(),
|
|
1630
|
+
imageWidth: IMAGE_WIDTH,
|
|
1631
|
+
imageHeight: IMAGE_HEIGHT,
|
|
1632
|
+
frames: SAMPLE_FRAME_NAMES.map(createFrame),
|
|
1633
|
+
animations: [
|
|
1634
|
+
...JIBBLE_DIRECTIONS.map(
|
|
1635
|
+
(direction) => createDirectionalAnimation(
|
|
1636
|
+
getJibbleAnimationId("idle", direction),
|
|
1637
|
+
"idle",
|
|
1638
|
+
direction,
|
|
1639
|
+
[`idle_${direction}`],
|
|
1640
|
+
1
|
|
1641
|
+
)
|
|
1642
|
+
),
|
|
1643
|
+
...JIBBLE_DIRECTIONS.map(
|
|
1644
|
+
(direction) => createDirectionalAnimation(
|
|
1645
|
+
getJibbleAnimationId("walk", direction),
|
|
1646
|
+
"walk",
|
|
1647
|
+
direction,
|
|
1648
|
+
Array.from({ length: WALK_FRAME_COUNT }, (_, index) => `walk_${direction}_${index}`),
|
|
1649
|
+
8
|
|
1650
|
+
)
|
|
1651
|
+
),
|
|
1652
|
+
{
|
|
1653
|
+
animationId: JIBBLE_ANIMATION.Backflip,
|
|
1654
|
+
role: "action",
|
|
1655
|
+
group: "jibble",
|
|
1656
|
+
direction: null,
|
|
1657
|
+
frameRate: 10,
|
|
1658
|
+
frames: BACKFLIP_FRAME_NAMES,
|
|
1659
|
+
facingFrameMap: null
|
|
1660
|
+
}
|
|
1661
|
+
]
|
|
1662
|
+
};
|
|
1663
|
+
function cloneTextureAtlas(atlas) {
|
|
1664
|
+
return {
|
|
1665
|
+
...atlas,
|
|
1666
|
+
frames: atlas.frames.map((frame) => ({ ...frame })),
|
|
1667
|
+
animations: atlas.animations.map((animation) => ({
|
|
1668
|
+
...animation,
|
|
1669
|
+
frames: [...animation.frames],
|
|
1670
|
+
facingFrameMap: animation.facingFrameMap ? { ...animation.facingFrameMap } : null
|
|
1671
|
+
}))
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
function getSampleTextureAtlas() {
|
|
1675
|
+
return cloneTextureAtlas(SAMPLE_TEXTURE_ATLAS);
|
|
1676
|
+
}
|
|
1677
|
+
function getSamplePlayerCharacter() {
|
|
1678
|
+
return {
|
|
1679
|
+
characterName: "SDK Sample Jibble",
|
|
1680
|
+
baseCharacterId: "sdk-sample-jibble",
|
|
1681
|
+
compositionCode: "sdk-sample-jibble-atlas-v1",
|
|
1682
|
+
textureAtlas: getSampleTextureAtlas(),
|
|
1683
|
+
editorTextureAtlas: getSampleTextureAtlas()
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
// src/character.ts
|
|
1688
|
+
var DEFAULT_SAMPLE_CHARACTER_URL = "https://api.oasiz.ai/api/sdk/sample-character";
|
|
1689
|
+
var DEFAULT_SAMPLE_FETCH_TIMEOUT_MS = 1500;
|
|
1690
|
+
function isDevelopment2() {
|
|
1691
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1692
|
+
return nodeEnv !== "production";
|
|
1693
|
+
}
|
|
1694
|
+
function getBridgeWindow2() {
|
|
1695
|
+
if (typeof window === "undefined") {
|
|
1696
|
+
return void 0;
|
|
1697
|
+
}
|
|
1698
|
+
return window;
|
|
1699
|
+
}
|
|
1700
|
+
function isLocalHostname(hostname) {
|
|
1701
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1" || hostname.endsWith(".localhost");
|
|
1702
|
+
}
|
|
1703
|
+
function shouldUseLocalFallback(bridge, localFallback) {
|
|
1704
|
+
if (localFallback === true) {
|
|
1705
|
+
return true;
|
|
1706
|
+
}
|
|
1707
|
+
if (localFallback === false) {
|
|
1708
|
+
return false;
|
|
1709
|
+
}
|
|
1710
|
+
const location = bridge?.location;
|
|
1711
|
+
if (!location) {
|
|
1712
|
+
return false;
|
|
1713
|
+
}
|
|
1714
|
+
return location.protocol === "file:" || isLocalHostname(location.hostname);
|
|
1715
|
+
}
|
|
1716
|
+
function warnMissingBridge2(methodName, usingFallback) {
|
|
1717
|
+
if (isDevelopment2()) {
|
|
1718
|
+
console.warn(
|
|
1719
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. " + (usingFallback ? "Using the SDK sample character atlas for local development." : "This is expected in local development.")
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
function isRecord2(value) {
|
|
1724
|
+
return typeof value === "object" && value !== null;
|
|
1725
|
+
}
|
|
1726
|
+
function isTextureAtlas(value) {
|
|
1727
|
+
if (!isRecord2(value)) {
|
|
1728
|
+
return false;
|
|
1729
|
+
}
|
|
1730
|
+
return typeof value.imageUrl === "string" && typeof value.imageWidth === "number" && Number.isFinite(value.imageWidth) && typeof value.imageHeight === "number" && Number.isFinite(value.imageHeight) && Array.isArray(value.frames) && Array.isArray(value.animations);
|
|
1731
|
+
}
|
|
1732
|
+
function isPlayerCharacter(value) {
|
|
1733
|
+
if (!isRecord2(value)) {
|
|
1734
|
+
return false;
|
|
1735
|
+
}
|
|
1736
|
+
return (typeof value.characterName === "string" || value.characterName === null) && typeof value.baseCharacterId === "string" && typeof value.compositionCode === "string" && isTextureAtlas(value.textureAtlas) && (value.editorTextureAtlas === null || isTextureAtlas(value.editorTextureAtlas));
|
|
1737
|
+
}
|
|
1738
|
+
function unwrapSampleCharacterResponse(payload) {
|
|
1739
|
+
if (isPlayerCharacter(payload)) {
|
|
1740
|
+
return payload;
|
|
1741
|
+
}
|
|
1742
|
+
if (isRecord2(payload) && isPlayerCharacter(payload.character)) {
|
|
1743
|
+
return payload.character;
|
|
1744
|
+
}
|
|
1745
|
+
return null;
|
|
1746
|
+
}
|
|
1747
|
+
async function fetchPlatformSampleCharacter(options) {
|
|
1748
|
+
if (typeof fetch !== "function") {
|
|
1749
|
+
return null;
|
|
1750
|
+
}
|
|
1751
|
+
const timeoutMs = options.sampleFetchTimeoutMs ?? DEFAULT_SAMPLE_FETCH_TIMEOUT_MS;
|
|
1752
|
+
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
|
1753
|
+
const timeout = controller && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : void 0;
|
|
1754
|
+
try {
|
|
1755
|
+
const response = await fetch(
|
|
1756
|
+
options.sampleCharacterUrl ?? DEFAULT_SAMPLE_CHARACTER_URL,
|
|
1757
|
+
{
|
|
1758
|
+
signal: controller?.signal
|
|
1759
|
+
}
|
|
1760
|
+
);
|
|
1761
|
+
if (!response.ok) {
|
|
1762
|
+
return null;
|
|
1763
|
+
}
|
|
1764
|
+
return unwrapSampleCharacterResponse(await response.json());
|
|
1765
|
+
} catch {
|
|
1766
|
+
return null;
|
|
1767
|
+
} finally {
|
|
1768
|
+
if (timeout) {
|
|
1769
|
+
clearTimeout(timeout);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
async function getPlayerCharacter(options = {}) {
|
|
1774
|
+
const bridge = getBridgeWindow2();
|
|
1775
|
+
if (typeof bridge?.__oasizGetPlayerCharacter !== "function") {
|
|
1776
|
+
const useLocalFallback = shouldUseLocalFallback(
|
|
1777
|
+
bridge,
|
|
1778
|
+
options.localFallback ?? "auto"
|
|
1779
|
+
);
|
|
1780
|
+
warnMissingBridge2("getPlayerCharacter", useLocalFallback);
|
|
1781
|
+
if (!useLocalFallback) {
|
|
1782
|
+
return null;
|
|
1783
|
+
}
|
|
1784
|
+
const platformSample = await fetchPlatformSampleCharacter(options);
|
|
1785
|
+
if (platformSample) {
|
|
1786
|
+
return platformSample;
|
|
1787
|
+
}
|
|
1788
|
+
return options.generatedFallback === false ? null : getSamplePlayerCharacter();
|
|
1789
|
+
}
|
|
1790
|
+
try {
|
|
1791
|
+
const result = await bridge.__oasizGetPlayerCharacter();
|
|
1792
|
+
return result ?? null;
|
|
1793
|
+
} catch (error) {
|
|
1794
|
+
if (isDevelopment2()) {
|
|
1795
|
+
console.error("[oasiz/sdk] getPlayerCharacter failed:", error);
|
|
1796
|
+
}
|
|
1797
|
+
return null;
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
// src/haptics.ts
|
|
1802
|
+
function isDevelopment3() {
|
|
1803
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1804
|
+
return nodeEnv !== "production";
|
|
1805
|
+
}
|
|
1806
|
+
function getBridgeWindow3() {
|
|
1807
|
+
if (typeof window === "undefined") {
|
|
1808
|
+
return void 0;
|
|
1809
|
+
}
|
|
1810
|
+
return window;
|
|
1811
|
+
}
|
|
1812
|
+
function triggerHaptic(type) {
|
|
1813
|
+
const bridge = getBridgeWindow3();
|
|
1814
|
+
if (typeof bridge?.triggerHaptic === "function") {
|
|
1815
|
+
bridge.triggerHaptic(type);
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
if (isDevelopment3()) {
|
|
1819
|
+
console.warn(
|
|
1820
|
+
"[oasiz/sdk] triggerHaptic bridge is unavailable. This is expected in local development."
|
|
1821
|
+
);
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1606
1825
|
// src/log-overlay.ts
|
|
1607
1826
|
var CONSOLE_METHODS = [
|
|
1608
1827
|
"debug",
|
|
@@ -2830,7 +3049,7 @@ function warnMissingBridge7(methodName) {
|
|
|
2830
3049
|
);
|
|
2831
3050
|
}
|
|
2832
3051
|
}
|
|
2833
|
-
function
|
|
3052
|
+
function isRecord3(value) {
|
|
2834
3053
|
return typeof value === "object" && value !== null;
|
|
2835
3054
|
}
|
|
2836
3055
|
function toFiniteNumber(value) {
|
|
@@ -2999,11 +3218,11 @@ function callBridgeFunction(bridge, name) {
|
|
|
2999
3218
|
}
|
|
3000
3219
|
}
|
|
3001
3220
|
function readInsetObjectValue(value, side, group) {
|
|
3002
|
-
if (!
|
|
3221
|
+
if (!isRecord3(value)) {
|
|
3003
3222
|
return void 0;
|
|
3004
3223
|
}
|
|
3005
3224
|
if (group) {
|
|
3006
|
-
return
|
|
3225
|
+
return isRecord3(value[group]) ? value[group][side] : void 0;
|
|
3007
3226
|
}
|
|
3008
3227
|
return value[side];
|
|
3009
3228
|
}
|
|
@@ -3140,7 +3359,7 @@ function getBridgeWindow10() {
|
|
|
3140
3359
|
}
|
|
3141
3360
|
return window;
|
|
3142
3361
|
}
|
|
3143
|
-
function
|
|
3362
|
+
function isRecord4(value) {
|
|
3144
3363
|
return typeof value === "object" && value !== null;
|
|
3145
3364
|
}
|
|
3146
3365
|
function toFiniteNumber2(value) {
|
|
@@ -3206,7 +3425,7 @@ function normalizeMetric(value) {
|
|
|
3206
3425
|
}
|
|
3207
3426
|
return void 0;
|
|
3208
3427
|
}
|
|
3209
|
-
if (!
|
|
3428
|
+
if (!isRecord4(value)) {
|
|
3210
3429
|
return void 0;
|
|
3211
3430
|
}
|
|
3212
3431
|
const fpsCandidate = firstDefined2(
|
|
@@ -3456,6 +3675,8 @@ var oasiz = {
|
|
|
3456
3675
|
addScore,
|
|
3457
3676
|
setScore,
|
|
3458
3677
|
getPlayerCharacter,
|
|
3678
|
+
getSamplePlayerCharacter,
|
|
3679
|
+
getSampleTextureAtlas,
|
|
3459
3680
|
share,
|
|
3460
3681
|
triggerHaptic,
|
|
3461
3682
|
enableLogOverlay,
|
|
@@ -3518,6 +3739,8 @@ var oasiz = {
|
|
|
3518
3739
|
getPlayerName,
|
|
3519
3740
|
getRoomCode,
|
|
3520
3741
|
getSafeAreaTop,
|
|
3742
|
+
getSamplePlayerCharacter,
|
|
3743
|
+
getSampleTextureAtlas,
|
|
3521
3744
|
getViewportInsets,
|
|
3522
3745
|
leaveGame,
|
|
3523
3746
|
loadGameState,
|
package/dist/index.d.cts
CHANGED
|
@@ -220,13 +220,35 @@ interface ScoreEditResult {
|
|
|
220
220
|
normalizedScore: number | null;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
interface GetPlayerCharacterOptions {
|
|
224
|
+
/**
|
|
225
|
+
* Controls the SDK sample character returned when the Oasiz app bridge is
|
|
226
|
+
* missing. `"auto"` returns the sample on localhost/file URLs only.
|
|
227
|
+
*/
|
|
228
|
+
localFallback?: boolean | "auto";
|
|
229
|
+
/**
|
|
230
|
+
* Public endpoint used for the real platform-generated local sample atlas.
|
|
231
|
+
*/
|
|
232
|
+
sampleCharacterUrl?: string;
|
|
233
|
+
/**
|
|
234
|
+
* Timeout for the public sample endpoint before falling back locally.
|
|
235
|
+
*/
|
|
236
|
+
sampleFetchTimeoutMs?: number;
|
|
237
|
+
/**
|
|
238
|
+
* When true, a tiny generated atlas is used if the platform sample endpoint
|
|
239
|
+
* is unavailable. Set false for strict platform-sample-only local testing.
|
|
240
|
+
*/
|
|
241
|
+
generatedFallback?: boolean;
|
|
242
|
+
}
|
|
223
243
|
/**
|
|
224
244
|
* Fetch the authenticated player's character, including a TexturePacker /
|
|
225
245
|
* Phaser-style texture atlas describing the baked sprite image.
|
|
226
246
|
*
|
|
227
247
|
* Returns:
|
|
228
248
|
* - `null` when the user has no character composition yet, OR
|
|
229
|
-
* -
|
|
249
|
+
* - a sample character atlas when the host bridge is unavailable on a local
|
|
250
|
+
* browser URL (`localhost` / `file://`), OR
|
|
251
|
+
* - `null` when the host bridge is unavailable and local fallback is disabled
|
|
230
252
|
*
|
|
231
253
|
* The host transparently caches and proxies to `GET /api/sdk/me/character`,
|
|
232
254
|
* so calling this multiple times in a session is cheap. The returned
|
|
@@ -245,7 +267,7 @@ interface ScoreEditResult {
|
|
|
245
267
|
* ),
|
|
246
268
|
* });
|
|
247
269
|
*/
|
|
248
|
-
declare function getPlayerCharacter(): Promise<PlayerCharacter | null>;
|
|
270
|
+
declare function getPlayerCharacter(options?: GetPlayerCharacterOptions): Promise<PlayerCharacter | null>;
|
|
249
271
|
|
|
250
272
|
declare function triggerHaptic(type: HapticType): void;
|
|
251
273
|
|
|
@@ -381,6 +403,9 @@ declare function loadGameState(): GameState;
|
|
|
381
403
|
declare function saveGameState(state: GameState): void;
|
|
382
404
|
declare function flushGameState(): void;
|
|
383
405
|
|
|
406
|
+
declare function getSampleTextureAtlas(): TextureAtlas;
|
|
407
|
+
declare function getSamplePlayerCharacter(): PlayerCharacter;
|
|
408
|
+
|
|
384
409
|
declare const oasiz: {
|
|
385
410
|
submitScore: typeof submitScore;
|
|
386
411
|
enableAppSimulator: typeof enableAppSimulator;
|
|
@@ -413,6 +438,8 @@ declare const oasiz: {
|
|
|
413
438
|
addScore: typeof addScore;
|
|
414
439
|
setScore: typeof setScore;
|
|
415
440
|
getPlayerCharacter: typeof getPlayerCharacter;
|
|
441
|
+
getSamplePlayerCharacter: typeof getSamplePlayerCharacter;
|
|
442
|
+
getSampleTextureAtlas: typeof getSampleTextureAtlas;
|
|
416
443
|
share: typeof share;
|
|
417
444
|
triggerHaptic: typeof triggerHaptic;
|
|
418
445
|
enableLogOverlay: typeof enableLogOverlay;
|
|
@@ -441,4 +468,4 @@ declare const oasiz: {
|
|
|
441
468
|
readonly graphicsPerformance: GraphicsPerformanceMetric;
|
|
442
469
|
};
|
|
443
470
|
|
|
444
|
-
export { type AppSimulatorDevice, type AppSimulatorDeviceName, type AppSimulatorHandle, type AppSimulatorOptions, type AppSimulatorOrientation, type BackButtonTestingHandle, type BackButtonTestingOptions, type FacingFrameMap, type GameState, type GraphicsPerformanceMetric, type GraphicsPerformanceTier, type HapticType, JIBBLE_ANIMATION, JIBBLE_ANIMATION_IDS, JIBBLE_DIRECTIONS, type JibbleAnimationAction, type JibbleAnimationId, type JibbleDirectionCode, type JibbleFacingDirection, type LogOverlayEntry, type LogOverlayHandle, type LogOverlayLevel, type LogOverlayOptions, type PlayerCharacter, type ScoreEditResult, type ShareRequest, type ShareRoomCodeOptions, type TextureAtlas, type TextureAtlasAnimation, type TextureAtlasFrame, type Unsubscribe, type ViewportInsetEdges, type ViewportInsetSide, type ViewportInsets, addScore, enableAppSimulator, enableBackButtonTesting, enableLogOverlay, flushGameState, getGameId, getGraphicsPerformance, getJibbleAnimationId, getPlayerAvatar, getPlayerCharacter, getPlayerId, getPlayerName, getRoomCode, getSafeAreaTop, getViewportInsets, leaveGame, loadGameState, normalizeJibbleDirection, oasiz, onBackButton, onLeaveGame, onPause, onResume, openInviteModal, saveGameState, setLeaderboardVisible, setScore, share, shareRoomCode, submitScore, triggerHaptic };
|
|
471
|
+
export { type AppSimulatorDevice, type AppSimulatorDeviceName, type AppSimulatorHandle, type AppSimulatorOptions, type AppSimulatorOrientation, type BackButtonTestingHandle, type BackButtonTestingOptions, type FacingFrameMap, type GameState, type GetPlayerCharacterOptions, type GraphicsPerformanceMetric, type GraphicsPerformanceTier, type HapticType, JIBBLE_ANIMATION, JIBBLE_ANIMATION_IDS, JIBBLE_DIRECTIONS, type JibbleAnimationAction, type JibbleAnimationId, type JibbleDirectionCode, type JibbleFacingDirection, type LogOverlayEntry, type LogOverlayHandle, type LogOverlayLevel, type LogOverlayOptions, type PlayerCharacter, type ScoreEditResult, type ShareRequest, type ShareRoomCodeOptions, type TextureAtlas, type TextureAtlasAnimation, type TextureAtlasFrame, type Unsubscribe, type ViewportInsetEdges, type ViewportInsetSide, type ViewportInsets, addScore, enableAppSimulator, enableBackButtonTesting, enableLogOverlay, flushGameState, getGameId, getGraphicsPerformance, getJibbleAnimationId, getPlayerAvatar, getPlayerCharacter, getPlayerId, getPlayerName, getRoomCode, getSafeAreaTop, getSamplePlayerCharacter, getSampleTextureAtlas, getViewportInsets, leaveGame, loadGameState, normalizeJibbleDirection, oasiz, onBackButton, onLeaveGame, onPause, onResume, openInviteModal, saveGameState, setLeaderboardVisible, setScore, share, shareRoomCode, submitScore, triggerHaptic };
|
package/dist/index.d.ts
CHANGED
|
@@ -220,13 +220,35 @@ interface ScoreEditResult {
|
|
|
220
220
|
normalizedScore: number | null;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
interface GetPlayerCharacterOptions {
|
|
224
|
+
/**
|
|
225
|
+
* Controls the SDK sample character returned when the Oasiz app bridge is
|
|
226
|
+
* missing. `"auto"` returns the sample on localhost/file URLs only.
|
|
227
|
+
*/
|
|
228
|
+
localFallback?: boolean | "auto";
|
|
229
|
+
/**
|
|
230
|
+
* Public endpoint used for the real platform-generated local sample atlas.
|
|
231
|
+
*/
|
|
232
|
+
sampleCharacterUrl?: string;
|
|
233
|
+
/**
|
|
234
|
+
* Timeout for the public sample endpoint before falling back locally.
|
|
235
|
+
*/
|
|
236
|
+
sampleFetchTimeoutMs?: number;
|
|
237
|
+
/**
|
|
238
|
+
* When true, a tiny generated atlas is used if the platform sample endpoint
|
|
239
|
+
* is unavailable. Set false for strict platform-sample-only local testing.
|
|
240
|
+
*/
|
|
241
|
+
generatedFallback?: boolean;
|
|
242
|
+
}
|
|
223
243
|
/**
|
|
224
244
|
* Fetch the authenticated player's character, including a TexturePacker /
|
|
225
245
|
* Phaser-style texture atlas describing the baked sprite image.
|
|
226
246
|
*
|
|
227
247
|
* Returns:
|
|
228
248
|
* - `null` when the user has no character composition yet, OR
|
|
229
|
-
* -
|
|
249
|
+
* - a sample character atlas when the host bridge is unavailable on a local
|
|
250
|
+
* browser URL (`localhost` / `file://`), OR
|
|
251
|
+
* - `null` when the host bridge is unavailable and local fallback is disabled
|
|
230
252
|
*
|
|
231
253
|
* The host transparently caches and proxies to `GET /api/sdk/me/character`,
|
|
232
254
|
* so calling this multiple times in a session is cheap. The returned
|
|
@@ -245,7 +267,7 @@ interface ScoreEditResult {
|
|
|
245
267
|
* ),
|
|
246
268
|
* });
|
|
247
269
|
*/
|
|
248
|
-
declare function getPlayerCharacter(): Promise<PlayerCharacter | null>;
|
|
270
|
+
declare function getPlayerCharacter(options?: GetPlayerCharacterOptions): Promise<PlayerCharacter | null>;
|
|
249
271
|
|
|
250
272
|
declare function triggerHaptic(type: HapticType): void;
|
|
251
273
|
|
|
@@ -381,6 +403,9 @@ declare function loadGameState(): GameState;
|
|
|
381
403
|
declare function saveGameState(state: GameState): void;
|
|
382
404
|
declare function flushGameState(): void;
|
|
383
405
|
|
|
406
|
+
declare function getSampleTextureAtlas(): TextureAtlas;
|
|
407
|
+
declare function getSamplePlayerCharacter(): PlayerCharacter;
|
|
408
|
+
|
|
384
409
|
declare const oasiz: {
|
|
385
410
|
submitScore: typeof submitScore;
|
|
386
411
|
enableAppSimulator: typeof enableAppSimulator;
|
|
@@ -413,6 +438,8 @@ declare const oasiz: {
|
|
|
413
438
|
addScore: typeof addScore;
|
|
414
439
|
setScore: typeof setScore;
|
|
415
440
|
getPlayerCharacter: typeof getPlayerCharacter;
|
|
441
|
+
getSamplePlayerCharacter: typeof getSamplePlayerCharacter;
|
|
442
|
+
getSampleTextureAtlas: typeof getSampleTextureAtlas;
|
|
416
443
|
share: typeof share;
|
|
417
444
|
triggerHaptic: typeof triggerHaptic;
|
|
418
445
|
enableLogOverlay: typeof enableLogOverlay;
|
|
@@ -441,4 +468,4 @@ declare const oasiz: {
|
|
|
441
468
|
readonly graphicsPerformance: GraphicsPerformanceMetric;
|
|
442
469
|
};
|
|
443
470
|
|
|
444
|
-
export { type AppSimulatorDevice, type AppSimulatorDeviceName, type AppSimulatorHandle, type AppSimulatorOptions, type AppSimulatorOrientation, type BackButtonTestingHandle, type BackButtonTestingOptions, type FacingFrameMap, type GameState, type GraphicsPerformanceMetric, type GraphicsPerformanceTier, type HapticType, JIBBLE_ANIMATION, JIBBLE_ANIMATION_IDS, JIBBLE_DIRECTIONS, type JibbleAnimationAction, type JibbleAnimationId, type JibbleDirectionCode, type JibbleFacingDirection, type LogOverlayEntry, type LogOverlayHandle, type LogOverlayLevel, type LogOverlayOptions, type PlayerCharacter, type ScoreEditResult, type ShareRequest, type ShareRoomCodeOptions, type TextureAtlas, type TextureAtlasAnimation, type TextureAtlasFrame, type Unsubscribe, type ViewportInsetEdges, type ViewportInsetSide, type ViewportInsets, addScore, enableAppSimulator, enableBackButtonTesting, enableLogOverlay, flushGameState, getGameId, getGraphicsPerformance, getJibbleAnimationId, getPlayerAvatar, getPlayerCharacter, getPlayerId, getPlayerName, getRoomCode, getSafeAreaTop, getViewportInsets, leaveGame, loadGameState, normalizeJibbleDirection, oasiz, onBackButton, onLeaveGame, onPause, onResume, openInviteModal, saveGameState, setLeaderboardVisible, setScore, share, shareRoomCode, submitScore, triggerHaptic };
|
|
471
|
+
export { type AppSimulatorDevice, type AppSimulatorDeviceName, type AppSimulatorHandle, type AppSimulatorOptions, type AppSimulatorOrientation, type BackButtonTestingHandle, type BackButtonTestingOptions, type FacingFrameMap, type GameState, type GetPlayerCharacterOptions, type GraphicsPerformanceMetric, type GraphicsPerformanceTier, type HapticType, JIBBLE_ANIMATION, JIBBLE_ANIMATION_IDS, JIBBLE_DIRECTIONS, type JibbleAnimationAction, type JibbleAnimationId, type JibbleDirectionCode, type JibbleFacingDirection, type LogOverlayEntry, type LogOverlayHandle, type LogOverlayLevel, type LogOverlayOptions, type PlayerCharacter, type ScoreEditResult, type ShareRequest, type ShareRoomCodeOptions, type TextureAtlas, type TextureAtlasAnimation, type TextureAtlasFrame, type Unsubscribe, type ViewportInsetEdges, type ViewportInsetSide, type ViewportInsets, addScore, enableAppSimulator, enableBackButtonTesting, enableLogOverlay, flushGameState, getGameId, getGraphicsPerformance, getJibbleAnimationId, getPlayerAvatar, getPlayerCharacter, getPlayerId, getPlayerName, getRoomCode, getSafeAreaTop, getSamplePlayerCharacter, getSampleTextureAtlas, getViewportInsets, leaveGame, loadGameState, normalizeJibbleDirection, oasiz, onBackButton, onLeaveGame, onPause, onResume, openInviteModal, saveGameState, setLeaderboardVisible, setScore, share, shareRoomCode, submitScore, triggerHaptic };
|
package/dist/index.js
CHANGED
|
@@ -1385,65 +1385,6 @@ function enableAppSimulator(options = {}) {
|
|
|
1385
1385
|
return handle;
|
|
1386
1386
|
}
|
|
1387
1387
|
|
|
1388
|
-
// src/character.ts
|
|
1389
|
-
function isDevelopment2() {
|
|
1390
|
-
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1391
|
-
return nodeEnv !== "production";
|
|
1392
|
-
}
|
|
1393
|
-
function getBridgeWindow2() {
|
|
1394
|
-
if (typeof window === "undefined") {
|
|
1395
|
-
return void 0;
|
|
1396
|
-
}
|
|
1397
|
-
return window;
|
|
1398
|
-
}
|
|
1399
|
-
function warnMissingBridge2(methodName) {
|
|
1400
|
-
if (isDevelopment2()) {
|
|
1401
|
-
console.warn(
|
|
1402
|
-
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1403
|
-
);
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
async function getPlayerCharacter() {
|
|
1407
|
-
const bridge = getBridgeWindow2();
|
|
1408
|
-
if (typeof bridge?.__oasizGetPlayerCharacter !== "function") {
|
|
1409
|
-
warnMissingBridge2("getPlayerCharacter");
|
|
1410
|
-
return null;
|
|
1411
|
-
}
|
|
1412
|
-
try {
|
|
1413
|
-
const result = await bridge.__oasizGetPlayerCharacter();
|
|
1414
|
-
return result ?? null;
|
|
1415
|
-
} catch (error) {
|
|
1416
|
-
if (isDevelopment2()) {
|
|
1417
|
-
console.error("[oasiz/sdk] getPlayerCharacter failed:", error);
|
|
1418
|
-
}
|
|
1419
|
-
return null;
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
// src/haptics.ts
|
|
1424
|
-
function isDevelopment3() {
|
|
1425
|
-
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1426
|
-
return nodeEnv !== "production";
|
|
1427
|
-
}
|
|
1428
|
-
function getBridgeWindow3() {
|
|
1429
|
-
if (typeof window === "undefined") {
|
|
1430
|
-
return void 0;
|
|
1431
|
-
}
|
|
1432
|
-
return window;
|
|
1433
|
-
}
|
|
1434
|
-
function triggerHaptic(type) {
|
|
1435
|
-
const bridge = getBridgeWindow3();
|
|
1436
|
-
if (typeof bridge?.triggerHaptic === "function") {
|
|
1437
|
-
bridge.triggerHaptic(type);
|
|
1438
|
-
return;
|
|
1439
|
-
}
|
|
1440
|
-
if (isDevelopment3()) {
|
|
1441
|
-
console.warn(
|
|
1442
|
-
"[oasiz/sdk] triggerHaptic bridge is unavailable. This is expected in local development."
|
|
1443
|
-
);
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
1388
|
// src/jibble.ts
|
|
1448
1389
|
var JIBBLE_DIRECTIONS = [
|
|
1449
1390
|
"n",
|
|
@@ -1544,6 +1485,282 @@ function getJibbleAnimationId(action, direction = "front") {
|
|
|
1544
1485
|
return `${action}_${normalizeJibbleDirection(direction)}`;
|
|
1545
1486
|
}
|
|
1546
1487
|
|
|
1488
|
+
// src/sample-character.ts
|
|
1489
|
+
var FRAME_SIZE = 32;
|
|
1490
|
+
var COLUMNS = 8;
|
|
1491
|
+
var WALK_FRAME_COUNT = 2;
|
|
1492
|
+
var BACKFLIP_FRAME_COUNT = 4;
|
|
1493
|
+
var COLORS = [
|
|
1494
|
+
"#2563eb",
|
|
1495
|
+
"#7c3aed",
|
|
1496
|
+
"#db2777",
|
|
1497
|
+
"#ea580c",
|
|
1498
|
+
"#16a34a",
|
|
1499
|
+
"#0891b2",
|
|
1500
|
+
"#4f46e5",
|
|
1501
|
+
"#be123c"
|
|
1502
|
+
];
|
|
1503
|
+
var IDLE_FRAME_NAMES = JIBBLE_DIRECTIONS.map((direction) => `idle_${direction}`);
|
|
1504
|
+
var WALK_FRAME_NAMES = JIBBLE_DIRECTIONS.flatMap(
|
|
1505
|
+
(direction) => Array.from({ length: WALK_FRAME_COUNT }, (_, index) => `walk_${direction}_${index}`)
|
|
1506
|
+
);
|
|
1507
|
+
var BACKFLIP_FRAME_NAMES = Array.from(
|
|
1508
|
+
{ length: BACKFLIP_FRAME_COUNT },
|
|
1509
|
+
(_, index) => `backflip_${index}`
|
|
1510
|
+
);
|
|
1511
|
+
var SAMPLE_FRAME_NAMES = [
|
|
1512
|
+
...IDLE_FRAME_NAMES,
|
|
1513
|
+
...WALK_FRAME_NAMES,
|
|
1514
|
+
...BACKFLIP_FRAME_NAMES
|
|
1515
|
+
];
|
|
1516
|
+
var IMAGE_WIDTH = COLUMNS * FRAME_SIZE;
|
|
1517
|
+
var IMAGE_HEIGHT = Math.ceil(SAMPLE_FRAME_NAMES.length / COLUMNS) * FRAME_SIZE;
|
|
1518
|
+
function getFrameRect(index) {
|
|
1519
|
+
return {
|
|
1520
|
+
x: index % COLUMNS * FRAME_SIZE,
|
|
1521
|
+
y: Math.floor(index / COLUMNS) * FRAME_SIZE,
|
|
1522
|
+
width: FRAME_SIZE,
|
|
1523
|
+
height: FRAME_SIZE
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
function createFrame(name, index) {
|
|
1527
|
+
return {
|
|
1528
|
+
name,
|
|
1529
|
+
...getFrameRect(index)
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
function getFrameLabel(name) {
|
|
1533
|
+
return name.replace(/^idle_/, "i ").replace(/^walk_/, "w ").replace(/^backflip_/, "flip ");
|
|
1534
|
+
}
|
|
1535
|
+
function createSvgDataUrl() {
|
|
1536
|
+
const cells = SAMPLE_FRAME_NAMES.map((name, index) => {
|
|
1537
|
+
const { x, y } = getFrameRect(index);
|
|
1538
|
+
const color = COLORS[index % COLORS.length];
|
|
1539
|
+
const label = getFrameLabel(name);
|
|
1540
|
+
return [
|
|
1541
|
+
`<rect x="${x}" y="${y}" width="${FRAME_SIZE}" height="${FRAME_SIZE}" fill="${color}"/>`,
|
|
1542
|
+
`<rect x="${x + 1}" y="${y + 1}" width="${FRAME_SIZE - 2}" height="${FRAME_SIZE - 2}" fill="none" stroke="#ffffff" stroke-opacity="0.35"/>`,
|
|
1543
|
+
`<circle cx="${x + 16}" cy="${y + 11}" r="5" fill="#ffffff" fill-opacity="0.92"/>`,
|
|
1544
|
+
`<rect x="${x + 12}" y="${y + 17}" width="8" height="7" rx="2" fill="#ffffff" fill-opacity="0.86"/>`,
|
|
1545
|
+
`<text x="${x + 16}" y="${y + 30}" text-anchor="middle" font-family="monospace" font-size="5" fill="#ffffff">${label}</text>`
|
|
1546
|
+
].join("");
|
|
1547
|
+
}).join("");
|
|
1548
|
+
const svg = [
|
|
1549
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${IMAGE_WIDTH}" height="${IMAGE_HEIGHT}" viewBox="0 0 ${IMAGE_WIDTH} ${IMAGE_HEIGHT}">`,
|
|
1550
|
+
`<rect width="${IMAGE_WIDTH}" height="${IMAGE_HEIGHT}" fill="#111827"/>`,
|
|
1551
|
+
cells,
|
|
1552
|
+
"</svg>"
|
|
1553
|
+
].join("");
|
|
1554
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
1555
|
+
}
|
|
1556
|
+
function createDirectionalAnimation(animationId, role, direction, frames, frameRate) {
|
|
1557
|
+
return {
|
|
1558
|
+
animationId,
|
|
1559
|
+
role,
|
|
1560
|
+
group: "jibble",
|
|
1561
|
+
direction,
|
|
1562
|
+
frameRate,
|
|
1563
|
+
frames,
|
|
1564
|
+
facingFrameMap: null
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
var SAMPLE_TEXTURE_ATLAS = {
|
|
1568
|
+
imageUrl: createSvgDataUrl(),
|
|
1569
|
+
imageWidth: IMAGE_WIDTH,
|
|
1570
|
+
imageHeight: IMAGE_HEIGHT,
|
|
1571
|
+
frames: SAMPLE_FRAME_NAMES.map(createFrame),
|
|
1572
|
+
animations: [
|
|
1573
|
+
...JIBBLE_DIRECTIONS.map(
|
|
1574
|
+
(direction) => createDirectionalAnimation(
|
|
1575
|
+
getJibbleAnimationId("idle", direction),
|
|
1576
|
+
"idle",
|
|
1577
|
+
direction,
|
|
1578
|
+
[`idle_${direction}`],
|
|
1579
|
+
1
|
|
1580
|
+
)
|
|
1581
|
+
),
|
|
1582
|
+
...JIBBLE_DIRECTIONS.map(
|
|
1583
|
+
(direction) => createDirectionalAnimation(
|
|
1584
|
+
getJibbleAnimationId("walk", direction),
|
|
1585
|
+
"walk",
|
|
1586
|
+
direction,
|
|
1587
|
+
Array.from({ length: WALK_FRAME_COUNT }, (_, index) => `walk_${direction}_${index}`),
|
|
1588
|
+
8
|
|
1589
|
+
)
|
|
1590
|
+
),
|
|
1591
|
+
{
|
|
1592
|
+
animationId: JIBBLE_ANIMATION.Backflip,
|
|
1593
|
+
role: "action",
|
|
1594
|
+
group: "jibble",
|
|
1595
|
+
direction: null,
|
|
1596
|
+
frameRate: 10,
|
|
1597
|
+
frames: BACKFLIP_FRAME_NAMES,
|
|
1598
|
+
facingFrameMap: null
|
|
1599
|
+
}
|
|
1600
|
+
]
|
|
1601
|
+
};
|
|
1602
|
+
function cloneTextureAtlas(atlas) {
|
|
1603
|
+
return {
|
|
1604
|
+
...atlas,
|
|
1605
|
+
frames: atlas.frames.map((frame) => ({ ...frame })),
|
|
1606
|
+
animations: atlas.animations.map((animation) => ({
|
|
1607
|
+
...animation,
|
|
1608
|
+
frames: [...animation.frames],
|
|
1609
|
+
facingFrameMap: animation.facingFrameMap ? { ...animation.facingFrameMap } : null
|
|
1610
|
+
}))
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
function getSampleTextureAtlas() {
|
|
1614
|
+
return cloneTextureAtlas(SAMPLE_TEXTURE_ATLAS);
|
|
1615
|
+
}
|
|
1616
|
+
function getSamplePlayerCharacter() {
|
|
1617
|
+
return {
|
|
1618
|
+
characterName: "SDK Sample Jibble",
|
|
1619
|
+
baseCharacterId: "sdk-sample-jibble",
|
|
1620
|
+
compositionCode: "sdk-sample-jibble-atlas-v1",
|
|
1621
|
+
textureAtlas: getSampleTextureAtlas(),
|
|
1622
|
+
editorTextureAtlas: getSampleTextureAtlas()
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
// src/character.ts
|
|
1627
|
+
var DEFAULT_SAMPLE_CHARACTER_URL = "https://api.oasiz.ai/api/sdk/sample-character";
|
|
1628
|
+
var DEFAULT_SAMPLE_FETCH_TIMEOUT_MS = 1500;
|
|
1629
|
+
function isDevelopment2() {
|
|
1630
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1631
|
+
return nodeEnv !== "production";
|
|
1632
|
+
}
|
|
1633
|
+
function getBridgeWindow2() {
|
|
1634
|
+
if (typeof window === "undefined") {
|
|
1635
|
+
return void 0;
|
|
1636
|
+
}
|
|
1637
|
+
return window;
|
|
1638
|
+
}
|
|
1639
|
+
function isLocalHostname(hostname) {
|
|
1640
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1" || hostname.endsWith(".localhost");
|
|
1641
|
+
}
|
|
1642
|
+
function shouldUseLocalFallback(bridge, localFallback) {
|
|
1643
|
+
if (localFallback === true) {
|
|
1644
|
+
return true;
|
|
1645
|
+
}
|
|
1646
|
+
if (localFallback === false) {
|
|
1647
|
+
return false;
|
|
1648
|
+
}
|
|
1649
|
+
const location = bridge?.location;
|
|
1650
|
+
if (!location) {
|
|
1651
|
+
return false;
|
|
1652
|
+
}
|
|
1653
|
+
return location.protocol === "file:" || isLocalHostname(location.hostname);
|
|
1654
|
+
}
|
|
1655
|
+
function warnMissingBridge2(methodName, usingFallback) {
|
|
1656
|
+
if (isDevelopment2()) {
|
|
1657
|
+
console.warn(
|
|
1658
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. " + (usingFallback ? "Using the SDK sample character atlas for local development." : "This is expected in local development.")
|
|
1659
|
+
);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
function isRecord2(value) {
|
|
1663
|
+
return typeof value === "object" && value !== null;
|
|
1664
|
+
}
|
|
1665
|
+
function isTextureAtlas(value) {
|
|
1666
|
+
if (!isRecord2(value)) {
|
|
1667
|
+
return false;
|
|
1668
|
+
}
|
|
1669
|
+
return typeof value.imageUrl === "string" && typeof value.imageWidth === "number" && Number.isFinite(value.imageWidth) && typeof value.imageHeight === "number" && Number.isFinite(value.imageHeight) && Array.isArray(value.frames) && Array.isArray(value.animations);
|
|
1670
|
+
}
|
|
1671
|
+
function isPlayerCharacter(value) {
|
|
1672
|
+
if (!isRecord2(value)) {
|
|
1673
|
+
return false;
|
|
1674
|
+
}
|
|
1675
|
+
return (typeof value.characterName === "string" || value.characterName === null) && typeof value.baseCharacterId === "string" && typeof value.compositionCode === "string" && isTextureAtlas(value.textureAtlas) && (value.editorTextureAtlas === null || isTextureAtlas(value.editorTextureAtlas));
|
|
1676
|
+
}
|
|
1677
|
+
function unwrapSampleCharacterResponse(payload) {
|
|
1678
|
+
if (isPlayerCharacter(payload)) {
|
|
1679
|
+
return payload;
|
|
1680
|
+
}
|
|
1681
|
+
if (isRecord2(payload) && isPlayerCharacter(payload.character)) {
|
|
1682
|
+
return payload.character;
|
|
1683
|
+
}
|
|
1684
|
+
return null;
|
|
1685
|
+
}
|
|
1686
|
+
async function fetchPlatformSampleCharacter(options) {
|
|
1687
|
+
if (typeof fetch !== "function") {
|
|
1688
|
+
return null;
|
|
1689
|
+
}
|
|
1690
|
+
const timeoutMs = options.sampleFetchTimeoutMs ?? DEFAULT_SAMPLE_FETCH_TIMEOUT_MS;
|
|
1691
|
+
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
|
1692
|
+
const timeout = controller && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : void 0;
|
|
1693
|
+
try {
|
|
1694
|
+
const response = await fetch(
|
|
1695
|
+
options.sampleCharacterUrl ?? DEFAULT_SAMPLE_CHARACTER_URL,
|
|
1696
|
+
{
|
|
1697
|
+
signal: controller?.signal
|
|
1698
|
+
}
|
|
1699
|
+
);
|
|
1700
|
+
if (!response.ok) {
|
|
1701
|
+
return null;
|
|
1702
|
+
}
|
|
1703
|
+
return unwrapSampleCharacterResponse(await response.json());
|
|
1704
|
+
} catch {
|
|
1705
|
+
return null;
|
|
1706
|
+
} finally {
|
|
1707
|
+
if (timeout) {
|
|
1708
|
+
clearTimeout(timeout);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
async function getPlayerCharacter(options = {}) {
|
|
1713
|
+
const bridge = getBridgeWindow2();
|
|
1714
|
+
if (typeof bridge?.__oasizGetPlayerCharacter !== "function") {
|
|
1715
|
+
const useLocalFallback = shouldUseLocalFallback(
|
|
1716
|
+
bridge,
|
|
1717
|
+
options.localFallback ?? "auto"
|
|
1718
|
+
);
|
|
1719
|
+
warnMissingBridge2("getPlayerCharacter", useLocalFallback);
|
|
1720
|
+
if (!useLocalFallback) {
|
|
1721
|
+
return null;
|
|
1722
|
+
}
|
|
1723
|
+
const platformSample = await fetchPlatformSampleCharacter(options);
|
|
1724
|
+
if (platformSample) {
|
|
1725
|
+
return platformSample;
|
|
1726
|
+
}
|
|
1727
|
+
return options.generatedFallback === false ? null : getSamplePlayerCharacter();
|
|
1728
|
+
}
|
|
1729
|
+
try {
|
|
1730
|
+
const result = await bridge.__oasizGetPlayerCharacter();
|
|
1731
|
+
return result ?? null;
|
|
1732
|
+
} catch (error) {
|
|
1733
|
+
if (isDevelopment2()) {
|
|
1734
|
+
console.error("[oasiz/sdk] getPlayerCharacter failed:", error);
|
|
1735
|
+
}
|
|
1736
|
+
return null;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
// src/haptics.ts
|
|
1741
|
+
function isDevelopment3() {
|
|
1742
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1743
|
+
return nodeEnv !== "production";
|
|
1744
|
+
}
|
|
1745
|
+
function getBridgeWindow3() {
|
|
1746
|
+
if (typeof window === "undefined") {
|
|
1747
|
+
return void 0;
|
|
1748
|
+
}
|
|
1749
|
+
return window;
|
|
1750
|
+
}
|
|
1751
|
+
function triggerHaptic(type) {
|
|
1752
|
+
const bridge = getBridgeWindow3();
|
|
1753
|
+
if (typeof bridge?.triggerHaptic === "function") {
|
|
1754
|
+
bridge.triggerHaptic(type);
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1757
|
+
if (isDevelopment3()) {
|
|
1758
|
+
console.warn(
|
|
1759
|
+
"[oasiz/sdk] triggerHaptic bridge is unavailable. This is expected in local development."
|
|
1760
|
+
);
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1547
1764
|
// src/log-overlay.ts
|
|
1548
1765
|
var CONSOLE_METHODS = [
|
|
1549
1766
|
"debug",
|
|
@@ -2771,7 +2988,7 @@ function warnMissingBridge7(methodName) {
|
|
|
2771
2988
|
);
|
|
2772
2989
|
}
|
|
2773
2990
|
}
|
|
2774
|
-
function
|
|
2991
|
+
function isRecord3(value) {
|
|
2775
2992
|
return typeof value === "object" && value !== null;
|
|
2776
2993
|
}
|
|
2777
2994
|
function toFiniteNumber(value) {
|
|
@@ -2940,11 +3157,11 @@ function callBridgeFunction(bridge, name) {
|
|
|
2940
3157
|
}
|
|
2941
3158
|
}
|
|
2942
3159
|
function readInsetObjectValue(value, side, group) {
|
|
2943
|
-
if (!
|
|
3160
|
+
if (!isRecord3(value)) {
|
|
2944
3161
|
return void 0;
|
|
2945
3162
|
}
|
|
2946
3163
|
if (group) {
|
|
2947
|
-
return
|
|
3164
|
+
return isRecord3(value[group]) ? value[group][side] : void 0;
|
|
2948
3165
|
}
|
|
2949
3166
|
return value[side];
|
|
2950
3167
|
}
|
|
@@ -3081,7 +3298,7 @@ function getBridgeWindow10() {
|
|
|
3081
3298
|
}
|
|
3082
3299
|
return window;
|
|
3083
3300
|
}
|
|
3084
|
-
function
|
|
3301
|
+
function isRecord4(value) {
|
|
3085
3302
|
return typeof value === "object" && value !== null;
|
|
3086
3303
|
}
|
|
3087
3304
|
function toFiniteNumber2(value) {
|
|
@@ -3147,7 +3364,7 @@ function normalizeMetric(value) {
|
|
|
3147
3364
|
}
|
|
3148
3365
|
return void 0;
|
|
3149
3366
|
}
|
|
3150
|
-
if (!
|
|
3367
|
+
if (!isRecord4(value)) {
|
|
3151
3368
|
return void 0;
|
|
3152
3369
|
}
|
|
3153
3370
|
const fpsCandidate = firstDefined2(
|
|
@@ -3397,6 +3614,8 @@ var oasiz = {
|
|
|
3397
3614
|
addScore,
|
|
3398
3615
|
setScore,
|
|
3399
3616
|
getPlayerCharacter,
|
|
3617
|
+
getSamplePlayerCharacter,
|
|
3618
|
+
getSampleTextureAtlas,
|
|
3400
3619
|
share,
|
|
3401
3620
|
triggerHaptic,
|
|
3402
3621
|
enableLogOverlay,
|
|
@@ -3458,6 +3677,8 @@ export {
|
|
|
3458
3677
|
getPlayerName,
|
|
3459
3678
|
getRoomCode,
|
|
3460
3679
|
getSafeAreaTop,
|
|
3680
|
+
getSamplePlayerCharacter,
|
|
3681
|
+
getSampleTextureAtlas,
|
|
3461
3682
|
getViewportInsets,
|
|
3462
3683
|
leaveGame,
|
|
3463
3684
|
loadGameState,
|