castle-web-cli 0.4.166 → 0.4.168

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 (112) hide show
  1. package/dist/agent.d.ts +1 -2
  2. package/dist/agent.js +22 -13
  3. package/dist/api.js +16 -1
  4. package/dist/castle-host/host.d.ts +2 -0
  5. package/dist/castle-host/host.js +17 -3
  6. package/dist/imports.js +19 -4
  7. package/dist/localPaths.d.ts +2 -0
  8. package/dist/localPaths.js +6 -0
  9. package/dist/platformDoc.js +1 -1
  10. package/dist/save-deck.js +13 -1
  11. package/dist/serve.js +7 -1
  12. package/dist/serveSecurity.d.ts +12 -0
  13. package/dist/serveSecurity.js +42 -0
  14. package/dist/shell/assets/index-CVHj503j.css +1 -0
  15. package/dist/shell/assets/index-D-qJ5VGp.js +425 -0
  16. package/dist/shell/index.html +2 -2
  17. package/kits/base/castle.json +64 -2
  18. package/kits/base/editors/ImageViewer.js +259 -0
  19. package/kits/base/editors/MediaPlayer.js +90 -0
  20. package/kits/base/editors/imageViewer.css +95 -0
  21. package/kits/base/editors/mediaPlayer.css +58 -0
  22. package/kits/base/sdk/README.md +3 -1
  23. package/kits/base/sdk/castle.d.ts +1 -0
  24. package/kits/base/sdk/commands.d.ts +7 -0
  25. package/kits/base/sdk/multiplayer.d.ts +6 -0
  26. package/kits/base/sdk/multiplayer.js +6 -0
  27. package/kits/blank/.castle/agent/children.json +1 -0
  28. package/kits/blank/.castle/agent/messages.json +9 -0
  29. package/kits/blank/.castle/agent/pending-sends.json +1 -0
  30. package/kits/blank/.castle/agent/tasks/index.md +2 -0
  31. package/kits/blank/.castle/docs/platform.md +36 -0
  32. package/kits/blank/node_modules/.vite/deps/_metadata.json +8 -0
  33. package/kits/blank/node_modules/.vite/deps/package.json +3 -0
  34. package/kits/multiplayer-2d/CLAUDE.md +6 -0
  35. package/kits/multiplayer-2d/castle.json +3 -3
  36. package/kits/multiplayer-2d/code/systems/multiplayer.js +5 -0
  37. package/kits/multiplayer-2d/package-lock.json +4 -1
  38. package/kits/multiplayer-3d/CLAUDE.md +6 -1
  39. package/kits/multiplayer-3d/castle.json +3 -3
  40. package/kits/multiplayer-3d/code/systems/multiplayer.js +5 -0
  41. package/kits/multiplayer-3d/package-lock.json +1 -1
  42. package/kits/physics-2d/behaviors/Joints.jsx +11 -5
  43. package/kits/physics-2d/behaviors/Sprite.jsx +6 -21
  44. package/kits/physics-2d/castle.json +1 -61
  45. package/kits/physics-2d/editors/BlueprintLibrary.jsx +8 -68
  46. package/kits/physics-2d/editors/SingleEditor.jsx +3 -10
  47. package/kits/physics-2d/editors/editorRegistry.jsx +36 -2
  48. package/kits/physics-2d/engine/art.js +25 -1
  49. package/kits/physics-2d/engine/artThumbnail.jsx +92 -0
  50. package/kits/physics-2d/engine/files.js +4 -15
  51. package/kits/physics-2d/engine/spriteField.jsx +176 -0
  52. package/kits/physics-2d/engine/ui.module.css +136 -0
  53. package/kits/physics-2d/package-lock.json +5 -0
  54. package/kits/physics-2d/pnpm-lock.yaml +96 -3
  55. package/kits/physics-3d/castle.json +1 -1
  56. package/kits/physics-3d/package-lock.json +1 -1
  57. package/kits/physics-3d/pnpm-lock.yaml +88 -3
  58. package/kits/real-time/CLAUDE.md +5 -0
  59. package/kits/real-time/castle.json +2 -2
  60. package/kits/real-time/code/client/connection.js +4 -0
  61. package/kits/real-time/code/client/gameHooks.js +3 -0
  62. package/kits/real-time/code/client/soloBadge.js +71 -0
  63. package/kits/real-time/package.json +3 -0
  64. package/kits/turn-based/castle.json +1 -1
  65. package/kits/turn-based/package-lock.json +1 -1
  66. package/package.json +1 -1
  67. package/dist/shell/assets/index-CG9TrvCm.js +0 -444
  68. package/dist/shell/assets/index-CIRBt1qf.css +0 -1
  69. package/kits/base/node_modules/.package-lock.json +0 -28
  70. package/kits/base/node_modules/castle-web-fonts/README.md +0 -114
  71. package/kits/base/node_modules/castle-web-fonts/dist/catalog.d.ts +0 -18
  72. package/kits/base/node_modules/castle-web-fonts/dist/catalog.js +0 -142
  73. package/kits/base/node_modules/castle-web-fonts/dist/face.d.ts +0 -1
  74. package/kits/base/node_modules/castle-web-fonts/dist/face.js +0 -52
  75. package/kits/base/node_modules/castle-web-fonts/dist/faces/Bore.d.ts +0 -3
  76. package/kits/base/node_modules/castle-web-fonts/dist/faces/Bore.js +0 -10
  77. package/kits/base/node_modules/castle-web-fonts/dist/faces/CourierPrime.d.ts +0 -3
  78. package/kits/base/node_modules/castle-web-fonts/dist/faces/CourierPrime.js +0 -10
  79. package/kits/base/node_modules/castle-web-fonts/dist/faces/DMSans.d.ts +0 -3
  80. package/kits/base/node_modules/castle-web-fonts/dist/faces/DMSans.js +0 -10
  81. package/kits/base/node_modules/castle-web-fonts/dist/faces/Glacier.d.ts +0 -3
  82. package/kits/base/node_modules/castle-web-fonts/dist/faces/Glacier.js +0 -10
  83. package/kits/base/node_modules/castle-web-fonts/dist/faces/HelicoCentrica.d.ts +0 -3
  84. package/kits/base/node_modules/castle-web-fonts/dist/faces/HelicoCentrica.js +0 -10
  85. package/kits/base/node_modules/castle-web-fonts/dist/faces/Piazzolla.d.ts +0 -3
  86. package/kits/base/node_modules/castle-web-fonts/dist/faces/Piazzolla.js +0 -10
  87. package/kits/base/node_modules/castle-web-fonts/dist/faces/Synco.d.ts +0 -3
  88. package/kits/base/node_modules/castle-web-fonts/dist/faces/Synco.js +0 -10
  89. package/kits/base/node_modules/castle-web-fonts/dist/faces/Tektur.d.ts +0 -3
  90. package/kits/base/node_modules/castle-web-fonts/dist/faces/Tektur.js +0 -10
  91. package/kits/base/node_modules/castle-web-fonts/dist/faces/YatraOne.d.ts +0 -3
  92. package/kits/base/node_modules/castle-web-fonts/dist/faces/YatraOne.js +0 -10
  93. package/kits/base/node_modules/castle-web-fonts/dist/index.d.ts +0 -16
  94. package/kits/base/node_modules/castle-web-fonts/dist/index.js +0 -15
  95. package/kits/base/node_modules/castle-web-fonts/licenses/CC-BY-ND-4.0.txt +0 -393
  96. package/kits/base/node_modules/castle-web-fonts/licenses/FONTS.md +0 -64
  97. package/kits/base/node_modules/castle-web-fonts/licenses/OFL-1.1.txt +0 -95
  98. package/kits/base/node_modules/castle-web-fonts/package.json +0 -47
  99. package/kits/base/node_modules/castle-web-fonts/woff2/Bore.woff2 +0 -0
  100. package/kits/base/node_modules/castle-web-fonts/woff2/CourierPrime.woff2 +0 -0
  101. package/kits/base/node_modules/castle-web-fonts/woff2/DMSans.woff2 +0 -0
  102. package/kits/base/node_modules/castle-web-fonts/woff2/Glacier.woff2 +0 -0
  103. package/kits/base/node_modules/castle-web-fonts/woff2/HelicoCentrica.woff2 +0 -0
  104. package/kits/base/node_modules/castle-web-fonts/woff2/Piazzolla.woff2 +0 -0
  105. package/kits/base/node_modules/castle-web-fonts/woff2/SOURCE.txt +0 -2
  106. package/kits/base/node_modules/castle-web-fonts/woff2/Synco.woff2 +0 -0
  107. package/kits/base/node_modules/castle-web-fonts/woff2/Tektur.woff2 +0 -0
  108. package/kits/base/node_modules/castle-web-fonts/woff2/YatraOne.woff2 +0 -0
  109. package/kits/physics-2d/editors/ImageViewer.jsx +0 -206
  110. package/kits/physics-2d/editors/MediaPlayer.jsx +0 -57
  111. package/kits/physics-2d/editors/mediaFile.js +0 -31
  112. package/kits/physics-2d/editors/mediaViewer.module.css +0 -128
@@ -23,18 +23,33 @@ importers:
23
23
  '@codemirror/view':
24
24
  specifier: ^6.41.1
25
25
  version: 6.43.1
26
+ '@dnd-kit/core':
27
+ specifier: ^6.3.1
28
+ version: 6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
29
+ '@dnd-kit/modifiers':
30
+ specifier: ^9.0.0
31
+ version: 9.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)
32
+ '@dnd-kit/sortable':
33
+ specifier: ^10.0.0
34
+ version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)
35
+ '@dnd-kit/utilities':
36
+ specifier: ^3.2.2
37
+ version: 3.2.2(react@19.2.7)
26
38
  '@fortawesome/free-solid-svg-icons':
27
39
  specifier: ^5.15.4
28
40
  version: 5.15.4
29
41
  '@lezer/highlight':
30
42
  specifier: ^1.2.3
31
43
  version: 1.2.3
32
- castle-web-sdk:
33
- specifier: file:../../sdk
34
- version: file:../../sdk
44
+ castle-web-fonts:
45
+ specifier: ^1.0.0
46
+ version: 1.0.0
35
47
  codemirror:
36
48
  specifier: ^6.0.2
37
49
  version: 6.0.2
50
+ matter-js:
51
+ specifier: ^0.20.0
52
+ version: 0.20.0
38
53
  react:
39
54
  specifier: ^19.2.4
40
55
  version: 19.2.7
@@ -42,6 +57,9 @@ importers:
42
57
  specifier: ^19.2.4
43
58
  version: 19.2.7(react@19.2.7)
44
59
  devDependencies:
60
+ castle-web-sdk:
61
+ specifier: file:../../sdk
62
+ version: file:../../sdk
45
63
  eslint:
46
64
  specifier: ^9.0.0
47
65
  version: 9.39.4
@@ -102,6 +120,34 @@ packages:
102
120
  resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
103
121
  engines: {node: '>=0.1.90'}
104
122
 
123
+ '@dnd-kit/accessibility@3.1.1':
124
+ resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
125
+ peerDependencies:
126
+ react: '>=16.8.0'
127
+
128
+ '@dnd-kit/core@6.3.1':
129
+ resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==}
130
+ peerDependencies:
131
+ react: '>=16.8.0'
132
+ react-dom: '>=16.8.0'
133
+
134
+ '@dnd-kit/modifiers@9.0.0':
135
+ resolution: {integrity: sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==}
136
+ peerDependencies:
137
+ '@dnd-kit/core': ^6.3.0
138
+ react: '>=16.8.0'
139
+
140
+ '@dnd-kit/sortable@10.0.0':
141
+ resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==}
142
+ peerDependencies:
143
+ '@dnd-kit/core': ^6.3.0
144
+ react: '>=16.8.0'
145
+
146
+ '@dnd-kit/utilities@3.2.2':
147
+ resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
148
+ peerDependencies:
149
+ react: '>=16.8.0'
150
+
105
151
  '@eslint-community/eslint-utils@4.9.1':
106
152
  resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
107
153
  engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -291,6 +337,9 @@ packages:
291
337
  resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
292
338
  engines: {node: '>=6'}
293
339
 
340
+ castle-web-fonts@1.0.0:
341
+ resolution: {integrity: sha512-amFts4vVJjaXKNQkh2DMMmxYHafCYczAOvme70n+0WX8fsTqJACh6r6MzND94l89Q6LFoIyrCm+cLh3S1Usy0w==}
342
+
294
343
  castle-web-sdk@file:../../sdk:
295
344
  resolution: {directory: ../../sdk, type: directory}
296
345
 
@@ -624,6 +673,9 @@ packages:
624
673
  resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
625
674
  engines: {node: '>= 0.4'}
626
675
 
676
+ matter-js@0.20.0:
677
+ resolution: {integrity: sha512-iC9fYR7zVT3HppNnsFsp9XOoQdQN2tUyfaKg4CHLH8bN+j6GT4Gw7IH2rP0tflAebrHFw730RR3DkVSZRX8hwA==}
678
+
627
679
  merge-stream@2.0.0:
628
680
  resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
629
681
 
@@ -836,6 +888,9 @@ packages:
836
888
  token-stream@1.0.0:
837
889
  resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==}
838
890
 
891
+ tslib@2.8.1:
892
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
893
+
839
894
  type-check@0.4.0:
840
895
  resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
841
896
  engines: {node: '>= 0.8.0'}
@@ -948,6 +1003,38 @@ snapshots:
948
1003
  '@colors/colors@1.5.0':
949
1004
  optional: true
950
1005
 
1006
+ '@dnd-kit/accessibility@3.1.1(react@19.2.7)':
1007
+ dependencies:
1008
+ react: 19.2.7
1009
+ tslib: 2.8.1
1010
+
1011
+ '@dnd-kit/core@6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
1012
+ dependencies:
1013
+ '@dnd-kit/accessibility': 3.1.1(react@19.2.7)
1014
+ '@dnd-kit/utilities': 3.2.2(react@19.2.7)
1015
+ react: 19.2.7
1016
+ react-dom: 19.2.7(react@19.2.7)
1017
+ tslib: 2.8.1
1018
+
1019
+ '@dnd-kit/modifiers@9.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)':
1020
+ dependencies:
1021
+ '@dnd-kit/core': 6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
1022
+ '@dnd-kit/utilities': 3.2.2(react@19.2.7)
1023
+ react: 19.2.7
1024
+ tslib: 2.8.1
1025
+
1026
+ '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)':
1027
+ dependencies:
1028
+ '@dnd-kit/core': 6.3.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
1029
+ '@dnd-kit/utilities': 3.2.2(react@19.2.7)
1030
+ react: 19.2.7
1031
+ tslib: 2.8.1
1032
+
1033
+ '@dnd-kit/utilities@3.2.2(react@19.2.7)':
1034
+ dependencies:
1035
+ react: 19.2.7
1036
+ tslib: 2.8.1
1037
+
951
1038
  '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4)':
952
1039
  dependencies:
953
1040
  eslint: 9.39.4
@@ -1149,6 +1236,8 @@ snapshots:
1149
1236
 
1150
1237
  callsites@3.1.0: {}
1151
1238
 
1239
+ castle-web-fonts@1.0.0: {}
1240
+
1152
1241
  castle-web-sdk@file:../../sdk: {}
1153
1242
 
1154
1243
  chalk@4.1.2:
@@ -1514,6 +1603,8 @@ snapshots:
1514
1603
 
1515
1604
  math-intrinsics@1.1.0: {}
1516
1605
 
1606
+ matter-js@0.20.0: {}
1607
+
1517
1608
  merge-stream@2.0.0: {}
1518
1609
 
1519
1610
  merge2@1.4.1: {}
@@ -1729,6 +1820,8 @@ snapshots:
1729
1820
 
1730
1821
  token-stream@1.0.0: {}
1731
1822
 
1823
+ tslib@2.8.1: {}
1824
+
1732
1825
  type-check@0.4.0:
1733
1826
  dependencies:
1734
1827
  prelude-ls: 1.2.1
@@ -69,5 +69,5 @@
69
69
  "autoUpdateWhenImported": true,
70
70
  "deckId": "JH0SclbPVP0y",
71
71
  "cardId": "eXfAaUdbSU5A",
72
- "publishedVersion": "2026-09-02T05:55:18.459Z"
72
+ "publishedVersion": "2026-09-05T00:07:37.655Z"
73
73
  }
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "../../sdk": {
37
37
  "name": "castle-web-sdk",
38
- "version": "0.4.23",
38
+ "version": "0.4.26",
39
39
  "dev": true,
40
40
  "devDependencies": {
41
41
  "eslint": "^9.0.0",
@@ -26,15 +26,27 @@ importers:
26
26
  '@dimforge/rapier3d-compat':
27
27
  specifier: ^0.19.2
28
28
  version: 0.19.3
29
+ '@dnd-kit/core':
30
+ specifier: ^6.3.1
31
+ version: 6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
32
+ '@dnd-kit/modifiers':
33
+ specifier: ^9.0.0
34
+ version: 9.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
35
+ '@dnd-kit/sortable':
36
+ specifier: ^10.0.0
37
+ version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)
38
+ '@dnd-kit/utilities':
39
+ specifier: ^3.2.2
40
+ version: 3.2.2(react@19.2.8)
29
41
  '@fortawesome/free-solid-svg-icons':
30
42
  specifier: ^5.15.4
31
43
  version: 5.15.4
32
44
  '@lezer/highlight':
33
45
  specifier: ^1.2.3
34
46
  version: 1.2.3
35
- castle-web-sdk:
36
- specifier: file:../../sdk
37
- version: file:../../sdk
47
+ castle-web-fonts:
48
+ specifier: ^1.0.0
49
+ version: 1.0.0
38
50
  codemirror:
39
51
  specifier: ^6.0.2
40
52
  version: 6.0.2
@@ -51,6 +63,9 @@ importers:
51
63
  specifier: ^0.180.0
52
64
  version: 0.180.0
53
65
  devDependencies:
66
+ castle-web-sdk:
67
+ specifier: file:../../sdk
68
+ version: file:../../sdk
54
69
  eslint:
55
70
  specifier: ^9.0.0
56
71
  version: 9.39.5
@@ -114,6 +129,34 @@ packages:
114
129
  '@dimforge/rapier3d-compat@0.19.3':
115
130
  resolution: {integrity: sha512-mMVdSj1PRTT108s9Swbu2GQOmHbn8kbJANRV5xfczL3s0T4vkgZAuoMRgvBzQcHanpKusbC0ZJj6z3mC3aj3vg==}
116
131
 
132
+ '@dnd-kit/accessibility@3.1.1':
133
+ resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
134
+ peerDependencies:
135
+ react: '>=16.8.0'
136
+
137
+ '@dnd-kit/core@6.3.1':
138
+ resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==}
139
+ peerDependencies:
140
+ react: '>=16.8.0'
141
+ react-dom: '>=16.8.0'
142
+
143
+ '@dnd-kit/modifiers@9.0.0':
144
+ resolution: {integrity: sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==}
145
+ peerDependencies:
146
+ '@dnd-kit/core': ^6.3.0
147
+ react: '>=16.8.0'
148
+
149
+ '@dnd-kit/sortable@10.0.0':
150
+ resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==}
151
+ peerDependencies:
152
+ '@dnd-kit/core': ^6.3.0
153
+ react: '>=16.8.0'
154
+
155
+ '@dnd-kit/utilities@3.2.2':
156
+ resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==}
157
+ peerDependencies:
158
+ react: '>=16.8.0'
159
+
117
160
  '@eslint-community/eslint-utils@4.10.1':
118
161
  resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==}
119
162
  engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -303,6 +346,9 @@ packages:
303
346
  resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
304
347
  engines: {node: '>=6'}
305
348
 
349
+ castle-web-fonts@1.0.0:
350
+ resolution: {integrity: sha512-amFts4vVJjaXKNQkh2DMMmxYHafCYczAOvme70n+0WX8fsTqJACh6r6MzND94l89Q6LFoIyrCm+cLh3S1Usy0w==}
351
+
306
352
  castle-web-sdk@file:../../sdk:
307
353
  resolution: {directory: ../../sdk, type: directory}
308
354
 
@@ -855,6 +901,9 @@ packages:
855
901
  token-stream@1.0.0:
856
902
  resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==}
857
903
 
904
+ tslib@2.8.1:
905
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
906
+
858
907
  type-check@0.4.0:
859
908
  resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
860
909
  engines: {node: '>= 0.8.0'}
@@ -969,6 +1018,38 @@ snapshots:
969
1018
 
970
1019
  '@dimforge/rapier3d-compat@0.19.3': {}
971
1020
 
1021
+ '@dnd-kit/accessibility@3.1.1(react@19.2.8)':
1022
+ dependencies:
1023
+ react: 19.2.8
1024
+ tslib: 2.8.1
1025
+
1026
+ '@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
1027
+ dependencies:
1028
+ '@dnd-kit/accessibility': 3.1.1(react@19.2.8)
1029
+ '@dnd-kit/utilities': 3.2.2(react@19.2.8)
1030
+ react: 19.2.8
1031
+ react-dom: 19.2.8(react@19.2.8)
1032
+ tslib: 2.8.1
1033
+
1034
+ '@dnd-kit/modifiers@9.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
1035
+ dependencies:
1036
+ '@dnd-kit/core': 6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
1037
+ '@dnd-kit/utilities': 3.2.2(react@19.2.8)
1038
+ react: 19.2.8
1039
+ tslib: 2.8.1
1040
+
1041
+ '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react@19.2.8)':
1042
+ dependencies:
1043
+ '@dnd-kit/core': 6.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
1044
+ '@dnd-kit/utilities': 3.2.2(react@19.2.8)
1045
+ react: 19.2.8
1046
+ tslib: 2.8.1
1047
+
1048
+ '@dnd-kit/utilities@3.2.2(react@19.2.8)':
1049
+ dependencies:
1050
+ react: 19.2.8
1051
+ tslib: 2.8.1
1052
+
972
1053
  '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5)':
973
1054
  dependencies:
974
1055
  eslint: 9.39.5
@@ -1170,6 +1251,8 @@ snapshots:
1170
1251
 
1171
1252
  callsites@3.1.0: {}
1172
1253
 
1254
+ castle-web-fonts@1.0.0: {}
1255
+
1173
1256
  castle-web-sdk@file:../../sdk: {}
1174
1257
 
1175
1258
  chalk@4.1.2:
@@ -1754,6 +1837,8 @@ snapshots:
1754
1837
 
1755
1838
  token-stream@1.0.0: {}
1756
1839
 
1840
+ tslib@2.8.1: {}
1841
+
1757
1842
  type-check@0.4.0:
1758
1843
  dependencies:
1759
1844
  prelude-ls: 1.2.1
@@ -59,6 +59,11 @@ never learns the format.
59
59
  values of a player pose are geometry before the `clamped` flag, and `epsilonAt`,
60
60
  which a kit whose pose values are all one unit leaves undefined.
61
61
 
62
+ `soloBadge.js` is the one file here that touches the DOM: a fixed badge that
63
+ names why a session fell back to solo (`status().soloReason` from
64
+ `connection.js`), drawn by both kits each frame through `updateSoloBadge`. It
65
+ stays dependency-free and hides itself when a deck's `soloBadge` hook says so.
66
+
62
67
  ## Rules for editing this kit
63
68
 
64
69
  **Root-anchor anything that reaches out.** Once imported these files live at
@@ -9,11 +9,11 @@
9
9
  "imports": {
10
10
  "castle.base": {
11
11
  "deckId": "yRcmH4_aYllE",
12
- "version": "2026-09-01T01:02:34.326Z"
12
+ "version": "2026-09-05T01:31:11.287Z"
13
13
  }
14
14
  },
15
15
  "autoUpdateWhenImported": true,
16
16
  "deckId": "xFVr-afOLuUQ",
17
17
  "cardId": "w6G45sy3_P_m",
18
- "publishedVersion": "2026-09-02T05:55:19.420Z"
18
+ "publishedVersion": "2026-09-05T01:31:28.578Z"
19
19
  }
@@ -90,6 +90,10 @@ export async function connectSession({ onLog = () => {} } = {}) {
90
90
  status: () => ({
91
91
  state: connection.state,
92
92
  solo: connection.isSolo,
93
+
94
+ // Why the join fell back to solo (`private_deck`, `no_server_bundle`, or
95
+ // `unavailable`), null while multiplayer is live. Drives soloBadge.js.
96
+ soloReason: connection.soloReason ?? null,
93
97
  others: Math.max(0, net.roster.size - 1),
94
98
 
95
99
  // The SDK derives `you` by finding the local id in its player list. Use
@@ -37,6 +37,9 @@ const modules = {
37
37
  // for one frame
38
38
  // afterFrame(scene, dt, system) after reporting
39
39
  // presence(status) the presence text a kit HUD shows
40
+ // soloBadge(status) the solo fallback badge (soloBadge.js):
41
+ // false hides it, a string replaces its text.
42
+ // Called every frame, so keep it a lookup
40
43
  // reset(scene, system) a scene load, after spawned actors are gone
41
44
  // and while the connection is still open
42
45
  // dispose(scene, system) runtime disposal, before reset and close
@@ -0,0 +1,71 @@
1
+ // A small on-screen badge for a session that fell back to solo, so a creator
2
+ // testing their own deck learns why nobody can join instead of guessing that
3
+ // multiplayer is broken. The two reasons a creator can fix name the fix; every
4
+ // other reason is a plain "unavailable" (the platform does not say more).
5
+ //
6
+ // Dependency-free DOM: the 2D and 3D kits draw their scenes differently, and
7
+ // neither has a shared HUD, so the badge lives outside both. A deck that wants
8
+ // its own treatment exports `soloBadge` from `code/client/game.js`: `false`
9
+ // suppresses it, a string replaces the text (see gameHooks.js).
10
+
11
+ const TEXT = {
12
+ private_deck: 'Solo: this deck is private',
13
+ no_server_bundle: 'Solo: publish the deck to enable multiplayer',
14
+ unavailable: 'Multiplayer unavailable',
15
+ };
16
+
17
+ // The badge text for a `status()` result, or null while multiplayer is live.
18
+ export function soloBadgeText(status) {
19
+ if (!status?.solo) {
20
+ return null;
21
+ }
22
+ return TEXT[status.soloReason] ?? TEXT.unavailable;
23
+ }
24
+
25
+ let element = null;
26
+ let shown = null;
27
+
28
+ // Show, update, or hide the badge to match `text`. Idempotent and cheap enough
29
+ // to call every frame: nothing touches the DOM unless the text changed.
30
+ export function showSoloBadge(text) {
31
+ if (text === shown || typeof document === 'undefined') {
32
+ return;
33
+ }
34
+ if (text === null) {
35
+ element?.remove();
36
+ element = null;
37
+ shown = null;
38
+ return;
39
+ }
40
+ if (!element) {
41
+ element = document.createElement('div');
42
+ element.setAttribute('data-castle-solo-badge', '');
43
+ element.style.cssText = [
44
+ 'position:fixed',
45
+ 'left:12px',
46
+ 'bottom:12px',
47
+ 'max-width:80vw',
48
+ 'padding:6px 10px',
49
+ 'border-radius:6px',
50
+ 'background:rgba(0,0,0,0.72)',
51
+ 'color:#fff',
52
+ 'font:500 12px/1.4 system-ui,sans-serif',
53
+ 'z-index:2147483647',
54
+ 'pointer-events:none',
55
+ ].join(';');
56
+ document.body.appendChild(element);
57
+ }
58
+ element.textContent = text;
59
+ // Recorded only once the DOM holds it, so a failed append is retried next
60
+ // frame rather than suppressing the badge for the rest of the session.
61
+ shown = text;
62
+ }
63
+
64
+ // The per-frame call a kit makes: the deck hook decides, then the badge follows.
65
+ export function updateSoloBadge(status, game) {
66
+ const custom = game?.soloBadge?.(status);
67
+ if (custom === false) {
68
+ return showSoloBadge(null);
69
+ }
70
+ showSoloBadge(typeof custom === 'string' ? custom : soloBadgeText(status));
71
+ }
@@ -10,5 +10,8 @@
10
10
  "castle-web-sdk": "file:../../sdk",
11
11
  "eslint": "^9.0.0",
12
12
  "prettier": "^3.8.3"
13
+ },
14
+ "dependencies": {
15
+ "castle-web-fonts": "^1.0.0"
13
16
  }
14
17
  }
@@ -28,7 +28,7 @@
28
28
  "autoUpdateWhenImported": true,
29
29
  "deckId": "K6-Xs7dCoMVi",
30
30
  "cardId": "Kh_08IYATpC3",
31
- "publishedVersion": "2026-09-02T05:55:21.391Z",
31
+ "publishedVersion": "2026-09-05T00:07:41.510Z",
32
32
  "server": {
33
33
  "main": "code/server/index.js",
34
34
  "maxPlayers": 8,
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "../../sdk": {
31
31
  "name": "castle-web-sdk",
32
- "version": "0.4.23",
32
+ "version": "0.4.26",
33
33
  "dev": true,
34
34
  "devDependencies": {
35
35
  "eslint": "^9.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "castle-web-cli",
3
- "version": "0.4.166",
3
+ "version": "0.4.168",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "castle-web": "./dist/index.js"