summer-engine 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +27 -5
  3. package/.codex-plugin/plugin.json +28 -6
  4. package/.cursor-plugin/plugin.json +27 -5
  5. package/.factory-plugin/plugin.json +27 -5
  6. package/.opencode/plugins/summer.js +1 -1
  7. package/CHANGELOG.md +102 -0
  8. package/README.md +18 -3
  9. package/assets/audit/scene_audit.gd +4136 -0
  10. package/assets/seeing/seeing_probe.gd +1873 -0
  11. package/dist/cli/commands/skills.js +20 -2
  12. package/dist/core/api-client.d.ts +9 -1
  13. package/dist/core/api-client.js +21 -4
  14. package/dist/core/capabilities/agent-playbook.js +46 -0
  15. package/dist/core/capabilities/audit/accept.d.ts +55 -0
  16. package/dist/core/capabilities/audit/accept.js +147 -0
  17. package/dist/core/capabilities/audit/args.d.ts +95 -0
  18. package/dist/core/capabilities/audit/args.js +89 -0
  19. package/dist/core/capabilities/audit/audit.d.ts +56 -0
  20. package/dist/core/capabilities/audit/audit.js +287 -0
  21. package/dist/core/capabilities/audit/frame.d.ts +14 -0
  22. package/dist/core/capabilities/audit/frame.js +35 -0
  23. package/dist/core/capabilities/audit/gaps.d.ts +96 -0
  24. package/dist/core/capabilities/audit/gaps.js +257 -0
  25. package/dist/core/capabilities/audit/judge.d.ts +162 -0
  26. package/dist/core/capabilities/audit/judge.js +1134 -0
  27. package/dist/core/capabilities/audit/math.d.ts +110 -0
  28. package/dist/core/capabilities/audit/math.js +263 -0
  29. package/dist/core/capabilities/audit/summary.d.ts +74 -0
  30. package/dist/core/capabilities/audit/summary.js +212 -0
  31. package/dist/core/capabilities/board.d.ts +31 -0
  32. package/dist/core/capabilities/board.js +43 -0
  33. package/dist/core/capabilities/camera-view.d.ts +4 -2
  34. package/dist/core/capabilities/camera-view.js +6 -3
  35. package/dist/core/capabilities/connect-signal.d.ts +85 -0
  36. package/dist/core/capabilities/connect-signal.js +285 -0
  37. package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
  38. package/dist/core/capabilities/engine-fallbacks.js +5 -0
  39. package/dist/core/capabilities/engine-ops.d.ts +5 -1
  40. package/dist/core/capabilities/engine-ops.js +0 -3
  41. package/dist/core/capabilities/engine-receipt.d.ts +12 -0
  42. package/dist/core/capabilities/engine-receipt.js +26 -0
  43. package/dist/core/capabilities/file-read.d.ts +64 -0
  44. package/dist/core/capabilities/file-read.js +325 -0
  45. package/dist/core/capabilities/game-task-plan.js +4 -2
  46. package/dist/core/capabilities/grep.d.ts +60 -0
  47. package/dist/core/capabilities/grep.js +190 -0
  48. package/dist/core/capabilities/inspect-node.d.ts +56 -0
  49. package/dist/core/capabilities/inspect-node.js +225 -0
  50. package/dist/core/capabilities/inspect-resource.d.ts +61 -0
  51. package/dist/core/capabilities/inspect-resource.js +376 -0
  52. package/dist/core/capabilities/math3d.d.ts +28 -0
  53. package/dist/core/capabilities/math3d.js +88 -0
  54. package/dist/core/capabilities/motion-generation.d.ts +62 -0
  55. package/dist/core/capabilities/motion-generation.js +138 -0
  56. package/dist/core/capabilities/placement-batch.d.ts +102 -0
  57. package/dist/core/capabilities/placement-batch.js +483 -0
  58. package/dist/core/capabilities/placement-math.d.ts +70 -0
  59. package/dist/core/capabilities/placement-math.js +209 -0
  60. package/dist/core/capabilities/placement-script.d.ts +42 -0
  61. package/dist/core/capabilities/placement-script.js +1096 -0
  62. package/dist/core/capabilities/placement.d.ts +485 -0
  63. package/dist/core/capabilities/placement.js +1731 -0
  64. package/dist/core/capabilities/project-context.d.ts +33 -2
  65. package/dist/core/capabilities/project-context.js +87 -4
  66. package/dist/core/capabilities/replace-node.d.ts +91 -0
  67. package/dist/core/capabilities/replace-node.js +423 -0
  68. package/dist/core/capabilities/runtime-control.d.ts +18 -2
  69. package/dist/core/capabilities/runtime-control.js +67 -2
  70. package/dist/core/capabilities/scene-batch.d.ts +63 -0
  71. package/dist/core/capabilities/scene-batch.js +394 -0
  72. package/dist/core/capabilities/scene-readback.d.ts +36 -0
  73. package/dist/core/capabilities/scene-readback.js +54 -0
  74. package/dist/core/capabilities/seeing/args.d.ts +348 -0
  75. package/dist/core/capabilities/seeing/args.js +178 -0
  76. package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
  77. package/dist/core/capabilities/seeing/candidates.js +282 -0
  78. package/dist/core/capabilities/seeing/math.d.ts +134 -0
  79. package/dist/core/capabilities/seeing/math.js +269 -0
  80. package/dist/core/capabilities/seeing/probe.d.ts +62 -0
  81. package/dist/core/capabilities/seeing/probe.js +188 -0
  82. package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
  83. package/dist/core/capabilities/seeing/scoring.js +639 -0
  84. package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
  85. package/dist/core/capabilities/seeing/seeing.js +1341 -0
  86. package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
  87. package/dist/core/capabilities/seeing/shot-store.js +204 -0
  88. package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
  89. package/dist/core/capabilities/surface-snap-mesh.js +425 -0
  90. package/dist/core/capabilities/surface-snap.d.ts +77 -0
  91. package/dist/core/capabilities/surface-snap.js +461 -0
  92. package/dist/core/capabilities/tool-dispatch.js +231 -72
  93. package/dist/core/capabilities/tscn.d.ts +85 -0
  94. package/dist/core/capabilities/tscn.js +391 -0
  95. package/dist/core/capabilities/world-snapshot.d.ts +58 -0
  96. package/dist/core/capabilities/world-snapshot.js +150 -0
  97. package/dist/core/capability-skew.d.ts +5 -5
  98. package/dist/core/capability-skew.js +14 -6
  99. package/dist/core/headless/worker-engine-client.d.ts +1 -1
  100. package/dist/core/headless/worker-engine-client.js +2 -2
  101. package/dist/core/library-read.d.ts +37 -5
  102. package/dist/core/library-read.js +264 -33
  103. package/dist/core/library-search.d.ts +2 -2
  104. package/dist/installer/agent-config.js +5 -3
  105. package/dist/installer/agent-table.d.ts +16 -0
  106. package/dist/installer/agent-table.js +52 -17
  107. package/dist/mcp/server.js +9 -3
  108. package/dist/mcp/tools/asset-tools.js +21 -3
  109. package/dist/mcp/tools/audit-tools.d.ts +23 -0
  110. package/dist/mcp/tools/audit-tools.js +60 -0
  111. package/dist/mcp/tools/debug-tools.js +3 -1
  112. package/dist/mcp/tools/file-tools.js +17 -4
  113. package/dist/mcp/tools/generate-tools.js +74 -66
  114. package/dist/mcp/tools/library-tools.js +2 -0
  115. package/dist/mcp/tools/perception-tools.js +6 -19
  116. package/dist/mcp/tools/placement-tools.d.ts +24 -0
  117. package/dist/mcp/tools/placement-tools.js +91 -0
  118. package/dist/mcp/tools/project-tools.js +18 -15
  119. package/dist/mcp/tools/scene-tools.js +71 -83
  120. package/dist/mcp/tools/seeing-tools.d.ts +24 -0
  121. package/dist/mcp/tools/seeing-tools.js +64 -0
  122. package/dist/mcp/tools/spatial-tools.js +17 -9
  123. package/dist/mcp/tools/visual-tools.js +59 -7
  124. package/gemini-extension.json +26 -4
  125. package/integrations/amp/README.md +1 -1
  126. package/integrations/crush/README.md +1 -1
  127. package/integrations/grok-build/README.md +1 -1
  128. package/integrations/hermes/README.md +1 -1
  129. package/integrations/kimi-code/README.md +1 -1
  130. package/integrations/mistral-vibe/README.md +1 -1
  131. package/integrations/opencode/README.md +1 -1
  132. package/integrations/rovo-dev/README.md +1 -1
  133. package/integrations/vscode-copilot/README.md +1 -1
  134. package/integrations/warp/README.md +1 -1
  135. package/integrations/windsurf/README.md +1 -1
  136. package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
  137. package/library/references/mcp-tools-reference/resource.yaml +1 -1
  138. package/library/references/summer-folder/resource.yaml +1 -1
  139. package/library/references/summer-folder/summer-folder.md +1 -1
  140. package/library/skills/3d-lighting/SKILL.md +1 -1
  141. package/library/skills/README.md +36 -14
  142. package/library/skills/adaptive-music/SKILL.md +1 -1
  143. package/library/skills/agent-playtesting/SKILL.md +1 -1
  144. package/library/skills/ai-characters-in-games/SKILL.md +220 -0
  145. package/library/skills/ai-characters-in-games/resource.yaml +30 -0
  146. package/library/skills/ambient-bed/SKILL.md +1 -1
  147. package/library/skills/animated-loop/SKILL.md +1 -1
  148. package/library/skills/animation-tree/SKILL.md +1 -1
  149. package/library/skills/art-direction/SKILL.md +1 -1
  150. package/library/skills/asset-strategy/SKILL.md +2 -1
  151. package/library/skills/asset-strategy/resource.yaml +2 -1
  152. package/library/skills/audio-direction/SKILL.md +1 -1
  153. package/library/skills/auto-fire-targeting/SKILL.md +1 -1
  154. package/library/skills/brainstorm-game/SKILL.md +1 -1
  155. package/library/skills/brainstorming/SKILL.md +1 -1
  156. package/library/skills/browse-templates/SKILL.md +3 -3
  157. package/library/skills/browse-templates/resource.yaml +1 -1
  158. package/library/skills/camera-rigs/SKILL.md +128 -0
  159. package/library/skills/camera-rigs/resource.yaml +29 -0
  160. package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
  161. package/library/skills/character-animation-wiring/SKILL.md +1 -1
  162. package/library/skills/character-model/SKILL.md +1 -1
  163. package/library/skills/character-movement/SKILL.md +326 -0
  164. package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
  165. package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
  166. package/library/skills/character-movement/references/movement-3d.md +136 -0
  167. package/library/skills/character-movement/references/platformer-feel.md +83 -0
  168. package/library/skills/character-movement/resource.yaml +40 -0
  169. package/library/skills/character-portrait/SKILL.md +1 -1
  170. package/library/skills/cinematic-cutscene/SKILL.md +1 -1
  171. package/library/skills/combat-basics/SKILL.md +159 -0
  172. package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
  173. package/library/skills/combat-basics/resource.yaml +34 -0
  174. package/library/skills/concept-art/SKILL.md +1 -1
  175. package/library/skills/create-asset-sheet/SKILL.md +1 -1
  176. package/library/skills/debug/SKILL.md +1 -1
  177. package/library/skills/debugging-game-feel/SKILL.md +1 -1
  178. package/library/skills/design-level/SKILL.md +1 -1
  179. package/library/skills/design-mechanic/SKILL.md +1 -1
  180. package/library/skills/design-npc/SKILL.md +1 -1
  181. package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
  182. package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
  183. package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
  184. package/library/skills/environment-kit/SKILL.md +1 -1
  185. package/library/skills/export-and-ship/SKILL.md +1 -1
  186. package/library/skills/fabricating-assets/SKILL.md +1 -1
  187. package/library/skills/facial-and-lipsync/SKILL.md +1 -1
  188. package/library/skills/fps-controller/SKILL.md +9 -7
  189. package/library/skills/fps-controller/resource.yaml +4 -1
  190. package/library/skills/game-feel/SKILL.md +1 -1
  191. package/library/skills/gameskill/SKILL.md +1 -1
  192. package/library/skills/gdscript-patterns/SKILL.md +1 -1
  193. package/library/skills/generate-motion/SKILL.md +9 -9
  194. package/library/skills/generate-motion/resource.yaml +2 -1
  195. package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
  196. package/library/skills/headless-scripting/SKILL.md +1 -1
  197. package/library/skills/in-game-purchases/SKILL.md +254 -0
  198. package/library/skills/in-game-purchases/resource.yaml +29 -0
  199. package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
  200. package/library/skills/investigating-bugs/SKILL.md +1 -1
  201. package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
  202. package/library/skills/make-game/SKILL.md +25 -3
  203. package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
  204. package/library/skills/make-game/references/2d-platformer.md +117 -0
  205. package/library/skills/make-game/references/2d-rpg-content.md +234 -0
  206. package/library/skills/make-game/references/2d-rpg.md +241 -0
  207. package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
  208. package/library/skills/make-game/references/2d-survivors.md +237 -0
  209. package/library/skills/make-game/references/3d-fps-systems.md +216 -0
  210. package/library/skills/make-game/references/3d-fps.md +177 -0
  211. package/library/skills/make-game/references/3d-horror-systems.md +186 -0
  212. package/library/skills/make-game/references/3d-horror.md +201 -0
  213. package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
  214. package/library/skills/make-game/references/3d-third-person.md +215 -0
  215. package/library/skills/make-game/resource.yaml +6 -1
  216. package/library/skills/multiplayer/SKILL.md +150 -0
  217. package/library/skills/multiplayer/resource.yaml +33 -0
  218. package/library/skills/multiplayer-movement/SKILL.md +510 -0
  219. package/library/skills/multiplayer-movement/files.md +501 -0
  220. package/library/skills/multiplayer-movement/resource.yaml +30 -0
  221. package/library/skills/multiplayer-project/SKILL.md +521 -0
  222. package/library/skills/multiplayer-project/files.md +448 -0
  223. package/library/skills/multiplayer-project/resource.yaml +36 -0
  224. package/library/skills/multiplayer-publish/SKILL.md +229 -0
  225. package/library/skills/multiplayer-publish/export-errors.md +89 -0
  226. package/library/skills/multiplayer-publish/resource.yaml +28 -0
  227. package/library/skills/multiplayer-state/SKILL.md +438 -0
  228. package/library/skills/multiplayer-state/files.md +592 -0
  229. package/library/skills/multiplayer-state/resource.yaml +35 -0
  230. package/library/skills/multiplayer-testing/SKILL.md +236 -0
  231. package/library/skills/multiplayer-testing/resource.yaml +39 -0
  232. package/library/skills/music-track/SKILL.md +1 -1
  233. package/library/skills/navigate-summer/SKILL.md +1 -1
  234. package/library/skills/new-project/SKILL.md +1 -1
  235. package/library/skills/organic-model/SKILL.md +1 -1
  236. package/library/skills/pixel-art/SKILL.md +1 -1
  237. package/library/skills/play/SKILL.md +1 -1
  238. package/library/skills/playtesting-a-feature/SKILL.md +1 -1
  239. package/library/skills/procedural-animation/SKILL.md +2 -2
  240. package/library/skills/procedural-animation/resource.yaml +1 -1
  241. package/library/skills/prop-model/SKILL.md +1 -1
  242. package/library/skills/psx-retro-rendering/SKILL.md +1 -1
  243. package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
  244. package/library/skills/remote-deploy/SKILL.md +1 -1
  245. package/library/skills/retarget/SKILL.md +1 -1
  246. package/library/skills/running-in-the-cloud/SKILL.md +1 -1
  247. package/library/skills/save-load/SKILL.md +156 -0
  248. package/library/skills/save-load/resource.yaml +27 -0
  249. package/library/skills/scene-composition/SKILL.md +1 -1
  250. package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
  251. package/library/skills/scene-scripting/SKILL.md +1 -1
  252. package/library/skills/scene-to-level/SKILL.md +1 -1
  253. package/library/skills/skill-create/SKILL.md +1 -1
  254. package/library/skills/skill-improve/SKILL.md +1 -1
  255. package/library/skills/skill-test/SKILL.md +1 -1
  256. package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
  257. package/library/skills/skybox-panorama/SKILL.md +1 -1
  258. package/library/skills/sound-effect/SKILL.md +1 -1
  259. package/library/skills/spatial-placement/SKILL.md +134 -3
  260. package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
  261. package/library/skills/spatial-placement/resource.yaml +16 -2
  262. package/library/skills/sprite-sheet/SKILL.md +1 -1
  263. package/library/skills/summer-analytics/SKILL.md +147 -0
  264. package/library/skills/summer-analytics/resource.yaml +28 -0
  265. package/library/skills/summer-friends/SKILL.md +226 -0
  266. package/library/skills/summer-friends/resource.yaml +28 -0
  267. package/library/skills/summer-leaderboards/SKILL.md +231 -0
  268. package/library/skills/summer-leaderboards/resource.yaml +30 -0
  269. package/library/skills/summer-match-results/SKILL.md +286 -0
  270. package/library/skills/summer-match-results/resource.yaml +32 -0
  271. package/library/skills/summer-matchmaking/SKILL.md +301 -0
  272. package/library/skills/summer-matchmaking/resource.yaml +32 -0
  273. package/library/skills/summer-parties/SKILL.md +253 -0
  274. package/library/skills/summer-parties/resource.yaml +30 -0
  275. package/library/skills/summer-player-data/SKILL.md +322 -0
  276. package/library/skills/summer-player-data/resource.yaml +30 -0
  277. package/library/skills/summer-store/SKILL.md +271 -0
  278. package/library/skills/summer-store/resource.yaml +29 -0
  279. package/library/skills/summer-world-chat/SKILL.md +195 -0
  280. package/library/skills/summer-world-chat/resource.yaml +30 -0
  281. package/library/skills/summer-world-saves/SKILL.md +284 -0
  282. package/library/skills/summer-world-saves/resource.yaml +29 -0
  283. package/library/skills/text-to-motion/SKILL.md +99 -0
  284. package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
  285. package/library/skills/text-to-motion/resource.yaml +41 -0
  286. package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
  287. package/library/skills/tileable-texture/SKILL.md +1 -1
  288. package/library/skills/trailer-shot/SKILL.md +1 -1
  289. package/library/skills/tune-performance/SKILL.md +1 -1
  290. package/library/skills/ui-basics/SKILL.md +10 -1
  291. package/library/skills/ui-graphics/SKILL.md +1 -1
  292. package/library/skills/use-widget-asset/SKILL.md +1 -1
  293. package/library/skills/using-summer/SKILL.md +2 -2
  294. package/library/skills/using-summer/resource.yaml +2 -2
  295. package/library/skills/vehicle-model/SKILL.md +1 -1
  296. package/library/skills/verification-before-completion/SKILL.md +1 -1
  297. package/library/skills/verifying-scenes/SKILL.md +76 -2
  298. package/library/skills/verifying-scenes/resource.yaml +13 -2
  299. package/library/skills/vfx-dissolve/SKILL.md +1 -1
  300. package/library/skills/vfx-fire/SKILL.md +1 -1
  301. package/library/skills/vfx-hit-spark/SKILL.md +1 -1
  302. package/library/skills/vfx-lightning/SKILL.md +1 -1
  303. package/library/skills/vfx-magic-glow/SKILL.md +1 -1
  304. package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
  305. package/library/skills/vfx-smoke/SKILL.md +1 -1
  306. package/library/skills/vfx-water-ripple/SKILL.md +1 -1
  307. package/library/skills/voice-line/SKILL.md +1 -1
  308. package/library/skills/web-and-touch-input/SKILL.md +38 -0
  309. package/library/skills/web-and-touch-input/resource.yaml +28 -0
  310. package/library/skills/web-compatibility-look/SKILL.md +62 -0
  311. package/library/skills/web-compatibility-look/resource.yaml +30 -0
  312. package/library/skills/world-building-3d/SKILL.md +8 -1
  313. package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
  314. package/library/skills/world-building-3d/resource.yaml +2 -1
  315. package/library/skills/writing-plans/SKILL.md +1 -1
  316. package/library/skills/writing-skills/SKILL.md +1 -1
  317. package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
  318. package/library/tools/attach-to-surface/resource.yaml +142 -0
  319. package/library/tools/batch/resource.yaml +9 -3
  320. package/library/tools/connect-ports/resource.yaml +120 -0
  321. package/library/tools/connect-signal/resource.yaml +3 -2
  322. package/library/tools/debug-views/resource.yaml +94 -0
  323. package/library/tools/frame-nodes/resource.yaml +104 -0
  324. package/library/tools/frame-shot/resource.yaml +134 -0
  325. package/library/tools/generate-motion/resource.yaml +44 -9
  326. package/library/tools/get-board/resource.yaml +50 -0
  327. package/library/tools/get-project-context/resource.yaml +13 -2
  328. package/library/tools/grep/resource.yaml +77 -0
  329. package/library/tools/inspect-asset/resource.yaml +71 -0
  330. package/library/tools/inspect-node/resource.yaml +9 -2
  331. package/library/tools/inspect-resource/resource.yaml +16 -5
  332. package/library/tools/instantiate-scene/resource.yaml +27 -2
  333. package/library/tools/measure/resource.yaml +96 -0
  334. package/library/tools/place-adjacent/resource.yaml +113 -0
  335. package/library/tools/play/resource.yaml +15 -2
  336. package/library/tools/raycast/resource.yaml +101 -0
  337. package/library/tools/read-file/resource.yaml +36 -2
  338. package/library/tools/read-library/resource.yaml +2 -2
  339. package/library/tools/repeat-along/resource.yaml +129 -0
  340. package/library/tools/replace-node/resource.yaml +11 -5
  341. package/library/tools/scene-audit/resource.yaml +144 -0
  342. package/library/tools/screenshot/resource.yaml +13 -2
  343. package/library/tools/search-assets/resource.yaml +18 -0
  344. package/library/tools/shot-sheet/resource.yaml +110 -0
  345. package/library/tools/snap-to-surface/resource.yaml +4 -1
  346. package/library/tools/world-snapshot/resource.yaml +24 -3
  347. package/library/tools/zoom/resource.yaml +105 -0
  348. package/package.json +1 -1
  349. package/registry/generated/aliases.json +17 -3
  350. package/registry/generated/counts.json +3 -3
  351. package/registry/generated/gemini-extension.json +26 -4
  352. package/registry/generated/index.json +2154 -469
  353. package/registry/generated/marketplace.claude.json +2 -2
  354. package/registry/generated/plugin.claude.json +27 -5
  355. package/registry/generated/plugin.codex.json +28 -6
  356. package/registry/generated/plugin.cursor.json +27 -5
  357. package/registry/generated/plugin.factory.json +27 -5
  358. package/registry/generated/skills-index.md +36 -14
  359. package/registry/generated/skills-registry.json +421 -124
  360. package/registry/generated/templates-registry.json +2 -2
  361. package/library/skills/host-authoritative-state/SKILL.md +0 -332
  362. package/library/skills/host-authoritative-state/resource.yaml +0 -28
  363. package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
  364. package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
  365. package/library/skills/setup-multiplayer/SKILL.md +0 -336
  366. package/library/skills/setup-multiplayer/resource.yaml +0 -28
@@ -0,0 +1,521 @@
1
+ ---
2
+ name: multiplayer-project
3
+ description: "Set up a Summer multiplayer project: both entry scenes, World and queue files, joining, and a first Local Play run."
4
+ license: MIT
5
+ compatibility: [Cursor, Claude Code, Windsurf, Codex]
6
+ category: multiplayer-and-networking
7
+ user-invocable: true
8
+ allowed-tools: Read Grep Glob Edit Write summer_read_file summer_write_file summer_get_scene_tree summer_get_script_errors summer_project_setting summer_play summer_stop summer_get_diagnostics
9
+ paths: ["project.godot", "summer.build.json", "world.json", "source-domains.json", "runtime-manifest.json", "network/**", "client/**", "authority/**"]
10
+ ---
11
+
12
+ # /multiplayer-project — the files every Summer multiplayer game needs
13
+
14
+ Step 1 of the multiplayer sequence (`multiplayer` explains the model). By the
15
+ end, Local Play starts a headless authority and two clients. Each client joins
16
+ through the game's own `Summer.client.join`, and every client sees one player
17
+ per joined player.
18
+
19
+ The example game is **Courtyard**. The later skills (`multiplayer-movement`,
20
+ `multiplayer-state`) continue it, so keep its names until the user's own game
21
+ replaces them. Every file below was run as shown with Local Play;
22
+ [files.md](files.md) has all of them complete, scenes included.
23
+
24
+ ## 1. Ask, then state the plan
25
+
26
+ > 1. What is the game called? Its id is `game_<name>`: lowercase letters, digits, `_`, `.` or `-`.
27
+ > 2. How many players per match? Summer measures up to 16.
28
+ > 3. Which platforms: iOS, macOS, Windows?
29
+
30
+ State the plan before writing anything:
31
+
32
+ > I'll add Summer multiplayer: a client scene and a headless authority scene,
33
+ > a World and a queue for 2–8 players, a network composition, and Local Play
34
+ > to test it. Each folder holds one side: `client/`, `authority/`,
35
+ > `network/` (shared). OK?
36
+
37
+ For an existing single-player game, get this skeleton running first, then
38
+ move its gameplay under `client/`.
39
+
40
+ ## 2. The layout
41
+
42
+ ```text
43
+ project.godot shared
44
+ summer.build.json the Build: game id, queues, Worlds, server preset
45
+ world.json the WorldDefinition: which scenes run where
46
+ runtime-manifest.json the server component's runtime descriptor
47
+ source-domains.json which folders are client, server or shared
48
+ network/ shared by both sides: composition, schemas, game.gd
49
+ client/ what players run: main scene, player scenes, UI
50
+ authority/ what the server runs: main scene, rules
51
+ ```
52
+
53
+ Client code and shared code must never load a file from `authority/`. The
54
+ summer.games export leaves `authority/` out of the players' pack. The
55
+ authority may load shared files.
56
+
57
+ ## 3. project.godot
58
+
59
+ Add to the project's `project.godot`:
60
+
61
+ ```ini
62
+ config_version=5
63
+
64
+ [application]
65
+
66
+ config/name="Courtyard"
67
+ run/main_scene="res://client/main.tscn"
68
+ run/main_scene.summer_client="res://client/main.tscn"
69
+ run/main_scene.summer_authority="res://authority/main.tscn"
70
+
71
+ [rendering]
72
+
73
+ textures/vram_compression/import_etc2_astc=true
74
+ ```
75
+
76
+ The `.summer_client` and `.summer_authority` overrides tell each exported pack
77
+ which scene to start. Leave the `[summer] version` line the editor writes.
78
+
79
+ ## 4. The declarations
80
+
81
+ `summer.build.json`: the game id, the queue players join, and the World it
82
+ starts. Summer rejects unknown fields, so copy the shape exactly.
83
+
84
+ ```json
85
+ {
86
+ "schema": "summer.build.v2",
87
+ "gameId": "game_courtyard",
88
+ "executionMode": "hosted",
89
+ "targetPlatforms": ["ios", "macos"],
90
+ "project": { "directory": "." },
91
+ "server": { "exportPreset": "Courtyard Authority" },
92
+ "runtime": {
93
+ "protocolVersion": "1.0.0",
94
+ "interfaces": {
95
+ "multiplayer": 6, "session": 3, "lobby": 3, "presence": 3,
96
+ "config": 3, "party": 1, "matchSearch": 1
97
+ },
98
+ "scenes": ["res://client/main.tscn"],
99
+ "worldDefinitions": ["world.json"],
100
+ "queues": [
101
+ {
102
+ "name": "courtyard",
103
+ "minPlayers": 2,
104
+ "maxPlayers": 8,
105
+ "worldDefinition": "courtyard",
106
+ "policy": "fifo",
107
+ "transport": "enet"
108
+ }
109
+ ],
110
+ "tickRate": 60,
111
+ "config": { "keys": {} },
112
+ "presence": { "tokens": {} },
113
+ "lobby": { "fields": {} },
114
+ "server": { "tier": "small" }
115
+ }
116
+ }
117
+ ```
118
+
119
+ - `queues[].minPlayers` / `maxPlayers` bound a match. `worldDefinition` names
120
+ the `definition_id` in `world.json`.
121
+ - `server.exportPreset` names the server export preset (`multiplayer-publish`).
122
+ - `runtime.interfaces`, `config`, `presence` and `lobby` are required. Copy
123
+ them as shown.
124
+
125
+ `world.json`: what one World is. Keep every field; Local Play accepts less,
126
+ but publishing needs all of them.
127
+
128
+ ```json
129
+ {
130
+ "schema": "summer.world-definition.v1",
131
+ "definition_id": "courtyard",
132
+ "lifetime": "match_scoped",
133
+ "topology": "dedicated",
134
+ "client_entry_point": "res://client/main.tscn",
135
+ "components": [
136
+ {
137
+ "component_id": "match",
138
+ "profile": "headless_engine",
139
+ "runtime_descriptor": "runtime-manifest.json",
140
+ "entry_point": "authority/main.tscn",
141
+ "owns": ["match"]
142
+ }
143
+ ],
144
+ "source_graph": "source-domains.json",
145
+ "network_compositions": ["res://network/composition.tres"],
146
+ "services": { "required": [], "optional": [] },
147
+ "settlement": { "mode": "required", "version": 1 },
148
+ "persistence": {
149
+ "mode": "none",
150
+ "recovery_point_seconds": 0,
151
+ "snapshot_schemas": [],
152
+ "migration_ids": []
153
+ },
154
+ "lifecycle": {
155
+ "reconnect_seconds": 30,
156
+ "drain_seconds": 5,
157
+ "transfer": "disabled",
158
+ "completion_owner": "world"
159
+ },
160
+ "placement": { "region_policy": "nearest" },
161
+ "limits_profile": "default"
162
+ }
163
+ ```
164
+
165
+ `runtime-manifest.json` describes the server component:
166
+
167
+ ```json
168
+ {
169
+ "profile": "headless_engine",
170
+ "entry_point": "authority/main.tscn",
171
+ "export_preset": "Courtyard Authority"
172
+ }
173
+ ```
174
+
175
+ `source-domains.json` marks the folders. The export uses it to keep server
176
+ code off players' devices:
177
+
178
+ ```json
179
+ {
180
+ "schema": "summer.source-domain-graph.v1",
181
+ "roots": [
182
+ { "domain": "shared", "paths": ["project.godot", "network", "world.json", "runtime-manifest.json"] },
183
+ { "domain": "client", "paths": ["client"] },
184
+ { "domain": "authority_engine", "paths": ["authority"] }
185
+ ],
186
+ "dependencies": []
187
+ }
188
+ ```
189
+
190
+ ## 5. The network composition
191
+
192
+ Both sides load the same composition. It declares every stream the game
193
+ sends, and client and authority refuse each other when theirs differ. Start
194
+ with one Command stream; later skills add more. `network/composition.tres`:
195
+
196
+ ```ini
197
+ [gd_resource type="SummerNetworkComposition" load_steps=6 format=3]
198
+
199
+ [sub_resource type="SummerNetworkField" id="CommandBytes"]
200
+ field_name = &"b"
201
+ type = 20
202
+
203
+ [sub_resource type="SummerNetworkSchema" id="CommandSchema"]
204
+ schema_id = &"courtyard.cmd.v1"
205
+ state_fields = Array[SummerNetworkField]([SubResource("CommandBytes")])
206
+
207
+ [sub_resource type="SummerNetworkField" id="ResultBytes"]
208
+ field_name = &"b"
209
+ type = 20
210
+
211
+ [sub_resource type="SummerNetworkSchema" id="ResultSchema"]
212
+ schema_id = &"courtyard.cmd.result.v1"
213
+ state_fields = Array[SummerNetworkField]([SubResource("ResultBytes")])
214
+
215
+ [sub_resource type="SummerNetworkOccurrenceStream" id="Commands"]
216
+ stream_id = &"courtyard.cmd"
217
+ command_scope = 2
218
+ command_tick_dispatch = true
219
+ command_timeout_msec = 8000
220
+ payload_schema = SubResource("CommandSchema")
221
+ result_schema = SubResource("ResultSchema")
222
+
223
+ [resource]
224
+ network_version = "1.0.0"
225
+ occurrence_streams = Array[SummerNetworkOccurrenceStream]([SubResource("Commands")])
226
+ ```
227
+
228
+ - A Command's payload and result travel as JSON in a byte field (`type = 20`,
229
+ `TYPE_PACKED_BYTE_ARRAY`): a network `String` holds at most 256 bytes.
230
+ - `command_scope = 2` is `COMMAND_SCOPE_WORLD`.
231
+ - `command_tick_dispatch = true` makes the authority handle a Command after
232
+ the tick's player poses are installed, so its checks use current positions.
233
+
234
+ The player entity's schema is empty, because players move through State
235
+ groups (`multiplayer-movement`). `network/player_schema.tres`:
236
+
237
+ ```ini
238
+ [gd_resource type="SummerNetworkSchema" format=3]
239
+
240
+ [resource]
241
+ schema_id = &"courtyard.player.v1"
242
+ ```
243
+
244
+ ## 6. Shared code
245
+
246
+ `network/game.gd` holds every id and builds the network nodes the same way
247
+ on both sides:
248
+
249
+ ```gdscript
250
+ extends RefCounted
251
+ ## Shared by the client and the authority: ids, streams and shared rules.
252
+
253
+ const GAME_ID := "game_courtyard"
254
+ const QUEUE := &"courtyard"
255
+ const CMD := &"courtyard.cmd"
256
+ const MAX_PLAYERS := 8
257
+ const COMPOSITION := preload("res://network/composition.tres")
258
+
259
+
260
+ ## Adds the World, an Entities root and the Spawner under `parent`. Both sides
261
+ ## pass their own player archetype; the composition is the same file.
262
+ static func build_network(parent: Node, player: SummerEntityArchetype) -> SummerNetworkSpawner:
263
+ var world := SummerNetworkWorld.new()
264
+ world.name = "World"
265
+ parent.add_child(world)
266
+ var entities := Node3D.new()
267
+ entities.name = "Entities"
268
+ parent.add_child(entities)
269
+ var spawner := SummerNetworkSpawner.new()
270
+ spawner.name = "Spawner"
271
+ spawner.network_world_path = NodePath("../World")
272
+ spawner.entities_root_path = NodePath("../Entities")
273
+ spawner.archetypes = [player]
274
+ spawner.player_archetype = &"player" # one entity per joined player
275
+ spawner.network_composition = COMPOSITION
276
+ parent.add_child(spawner)
277
+ return spawner
278
+
279
+
280
+ ## Commands and results travel as JSON bytes: a network String holds at most
281
+ ## 256 bytes.
282
+ static func pack(document: Dictionary) -> Dictionary:
283
+ return {"b": JSON.stringify(document).to_utf8_buffer()}
284
+
285
+
286
+ static func unpack(fields: Dictionary) -> Dictionary:
287
+ var parsed: Variant = JSON.parse_string((fields.get("b", PackedByteArray()) as PackedByteArray).get_string_from_utf8())
288
+ return parsed if parsed is Dictionary else {}
289
+ ```
290
+
291
+ Each side passes its own **player archetype**: the scenes the Spawner spawns
292
+ for every joined player. The authority gets a model with no visuals. Clients
293
+ get an owner scene for their own player and an observer scene for everyone
294
+ else. Splitting them keeps client scenes out of the server and server scenes
295
+ out of the client.
296
+
297
+ ## 7. The authority
298
+
299
+ The authority's player archetype, `authority/player_archetype.tres`, names
300
+ only an `authority_model_scene`: `authority/player_model.tscn`, a bare
301
+ `Node3D`. Both are in [files.md](files.md).
302
+
303
+ `authority/main.gd` initializes Summer, waits for its World, and answers the
304
+ `join` Command:
305
+
306
+ ```gdscript
307
+ extends Node
308
+ ## The match server. It runs headless and owns every rule.
309
+
310
+ const Game = preload("res://network/game.gd")
311
+ const PlayerArchetype = preload("res://authority/player_archetype.tres")
312
+
313
+ var spawner: SummerNetworkSpawner
314
+ var world: SummerNetworkWorld
315
+ var seat_of := {} # session_id -> seat, held until the Session leaves
316
+
317
+
318
+ func _ready() -> void:
319
+ spawner = Game.build_network(self, PlayerArchetype)
320
+ world = $World
321
+ spawner.entity_spawned.connect(_on_player_spawned)
322
+ spawner.command_received.connect(_on_command)
323
+ world.session_left.connect(_on_session_left)
324
+ var initialized: SummerResult = await Summer.initialize(Game.GAME_ID).get_result_or_completed_signal()
325
+ if not initialized.ok:
326
+ push_error(initialized.message)
327
+ return
328
+ if not world.is_ready():
329
+ await world.binding_ready
330
+ if not spawner.is_network_ready():
331
+ await spawner.network_ready
332
+ print("COURTYARD_AUTHORITY_READY")
333
+
334
+
335
+ ## A seat is a player's place in this World for their whole stay, across
336
+ ## reconnects. Returns -1 when the World is full.
337
+ func _seat(session: SummerSession) -> int:
338
+ if seat_of.has(session.session_id):
339
+ return seat_of[session.session_id]
340
+ var taken := seat_of.values()
341
+ for seat in Game.MAX_PLAYERS:
342
+ if seat not in taken:
343
+ seat_of[session.session_id] = seat
344
+ return seat
345
+ return -1
346
+
347
+
348
+ ## The Spawner spawns one player entity per joined player, once that player's
349
+ ## network is ready (and again after a reconnect).
350
+ func _on_player_spawned(entity: SummerNetworkEntity) -> void:
351
+ print("COURTYARD_PLAYER_SPAWNED seat=%d entity=%d" % [_seat(entity.session), entity.entity_id])
352
+
353
+
354
+ func _on_command(request: SummerNetworkCommandRequest) -> void:
355
+ var command := Game.unpack(request.payload)
356
+ match str(command.get("c", "")):
357
+ "join":
358
+ _join(request)
359
+ _:
360
+ request.refuse(&"unknown_command")
361
+
362
+
363
+ ## A client sends "join" once its network is ready.
364
+ func _join(request: SummerNetworkCommandRequest) -> void:
365
+ var seat := _seat(request.get_session())
366
+ if seat < 0:
367
+ request.refuse(&"match_full")
368
+ return
369
+ request.accept({}, Game.pack({"seat": seat}))
370
+ print("COURTYARD_PLAYER_JOINED seat=%d" % seat)
371
+
372
+
373
+ ## The Session ended for good: free the seat and everything the player had.
374
+ func _on_session_left(session: SummerSession, reason: String) -> void:
375
+ var seat: int = seat_of.get(session.session_id, -1)
376
+ seat_of.erase(session.session_id)
377
+ print("COURTYARD_PLAYER_LEFT seat=%d reason=%s" % [seat, reason])
378
+ ```
379
+
380
+ `authority/main.tscn` is a plain `Node` with that script ([files.md](files.md)).
381
+
382
+ - **Never** read who sent a Command from its payload: `request.get_session()`
383
+ is verified. Don't name your own classes `SummerSession`, `SummerWorld` or
384
+ other engine class names.
385
+ - `session_disconnected` means the player's connection dropped and their seat
386
+ is held. `session_left` means they are gone for good. Free their things in
387
+ `session_left` only. Under Local Play it arrives when the World ends.
388
+
389
+ ## 8. The client
390
+
391
+ The client's player archetype, `client/player_archetype.tres`, names an
392
+ `owner_projection_scene` and an `observer_projection_scene`:
393
+
394
+ ```ini
395
+ [gd_resource type="SummerEntityArchetype" load_steps=4 format=3]
396
+
397
+ [ext_resource type="SummerNetworkSchema" path="res://network/player_schema.tres" id="1"]
398
+ [ext_resource type="PackedScene" path="res://client/player_owner.tscn" id="2"]
399
+ [ext_resource type="PackedScene" path="res://client/player_observer.tscn" id="3"]
400
+
401
+ [resource]
402
+ archetype_id = &"player"
403
+ network_schema = ExtResource("1")
404
+ owner_projection_scene = ExtResource("2")
405
+ observer_projection_scene = ExtResource("3")
406
+ ```
407
+
408
+ `client/player_owner.tscn` is a `CharacterBody3D` with a capsule and the
409
+ camera. `client/player_observer.tscn` is a `Node3D` with a capsule and no
410
+ collision. Both are in [files.md](files.md).
411
+
412
+ `client/main.gd` joins the queue, waits until the network is ready, then
413
+ tells the authority it has arrived:
414
+
415
+ ```gdscript
416
+ extends Node
417
+ ## What each player runs: joins the match and shows every player.
418
+
419
+ const Game = preload("res://network/game.gd")
420
+ const PlayerArchetype = preload("res://client/player_archetype.tres")
421
+
422
+ var spawner: SummerNetworkSpawner
423
+
424
+
425
+ func _ready() -> void:
426
+ spawner = Game.build_network(self, PlayerArchetype)
427
+ # Connect signals like state_group_created here, before joining, or values
428
+ # that arrive during the join go unseen (multiplayer-movement adds them).
429
+ var initialized: SummerResult = await Summer.initialize(Game.GAME_ID).get_result_or_completed_signal()
430
+ if not initialized.ok:
431
+ push_error(initialized.message)
432
+ return
433
+ var join := Summer.client.join(SummerJoinTarget.queue(Game.QUEUE))
434
+ # Hosted matchmaking may ask the player to accept a match.
435
+ join.acceptance_required.connect(func(proposal: SummerMatchmakingProposal) -> void: proposal.accept())
436
+ var joined: SummerResult = await join.get_result_or_completed_signal()
437
+ if not joined.ok:
438
+ push_error("join failed: %s %s" % [joined.code, joined.message])
439
+ return
440
+ if not spawner.is_network_ready():
441
+ await spawner.network_ready
442
+ var entered := await command({"c": "join"})
443
+ if not entered.ok:
444
+ push_error("could not enter the match: %s" % entered.error)
445
+ return
446
+ print("COURTYARD_CLIENT_JOINED")
447
+
448
+
449
+ ## Sends one Command and waits for the authority's answer.
450
+ func command(payload: Dictionary) -> Dictionary:
451
+ var admission := spawner.enqueue_command(Game.CMD, Game.pack(payload))
452
+ if not admission.is_enqueued():
453
+ return {"ok": false, "error": String(admission.get_code())}
454
+ var handle := admission.get_handle()
455
+ if not handle.is_terminal():
456
+ await handle.completed
457
+ if handle.get_outcome() == SummerNetworkCommandHandle.OUTCOME_ACCEPTED:
458
+ return {"ok": true, "error": "", "result": Game.unpack(handle.get_result())}
459
+ return {"ok": false, "error": String(handle.get_reason())}
460
+ ```
461
+
462
+ `client/main.tscn` holds the level (a floor and a light) and that script
463
+ ([files.md](files.md)).
464
+
465
+ - Connect `state_group_created` and `entity_spawned` **before** joining, or
466
+ values that arrive during the join go unseen.
467
+ - `Summer.client.join` succeeding means the player has a seat. Send Commands
468
+ only after `spawner.network_ready`.
469
+ - Hosted, matchmaking may ask the player to accept a match. This skeleton
470
+ accepts it right away; `summer-matchmaking` shows a real prompt.
471
+
472
+ ## 9. Run it with Local Play
473
+
474
+ Import once so new scripts register, then start two players.
475
+
476
+ With the Summer MCP tools:
477
+
478
+ ```
479
+ summer_project_setting name="summer/local_play/players" value=2
480
+ summer_play
481
+ summer_get_diagnostics
482
+ summer_stop
483
+ ```
484
+
485
+ In the editor, **Debug > Local Multiplayer** sets the same player count; then
486
+ press Play. From a terminal (`<summer>` is the Summer editor executable):
487
+
488
+ ```sh
489
+ <summer> --headless --path . --import
490
+ <summer> --path . --summer-local-play 2 --summer-local-play-headless --summer-local-play-timeout 15
491
+ ```
492
+
493
+ Read the processes' output. Each line is prefixed with `[authority]`,
494
+ `[player-1]` or `[player-2]`:
495
+
496
+ - [ ] `[authority] COURTYARD_AUTHORITY_READY`
497
+ - [ ] `[authority] COURTYARD_PLAYER_SPAWNED` twice and `COURTYARD_PLAYER_JOINED` twice
498
+ - [ ] `COURTYARD_CLIENT_JOINED` from each player
499
+ - [ ] No `SCRIPT ERROR`, and no `[SummerNetworkSpawner] cannot attach` warning
500
+ - [ ] The last line, `SUMMER_LOCAL_PLAY_RESULT {...}`, has `"ok":true` and `"script_errors":0` for every process
501
+
502
+ `cannot attach` means the composition is invalid, and nothing networked will
503
+ work. Local Play still reports every client as joined, so look for the
504
+ warning yourself.
505
+
506
+ ## Common mistakes
507
+
508
+ | Don't | Do | Why |
509
+ |---|---|---|
510
+ | `@rpc`, `MultiplayerSynchronizer`, `ENetMultiplayerPeer` | The Spawner, State groups and Commands | Unverified peers, no late join, no Summer hosting |
511
+ | `if multiplayer.is_server()` in one shared scene | Separate `client/` and `authority/` scenes | The engine starts the right scene on each side |
512
+ | Load an `authority/` file from client or shared code | Move what both sides need into `network/` | The export leaves `authority/` out of the players' pack |
513
+ | Build the composition differently on each side | One `network/composition.tres`, loaded by both | Different compositions refuse each other |
514
+ | Send a Command right after `join` succeeds | Await `spawner.network_ready` first | The authority does not know the client's network until then |
515
+ | Free a player's things on `session_disconnected` | Free them on `session_left` | A disconnected player keeps their seat and may reconnect |
516
+ | Trust "every client joined" alone | Also check for `cannot attach` and your own ready lines | A broken composition still joins |
517
+
518
+ ## Next
519
+
520
+ `multiplayer-movement`: each player moves their own character, and everyone
521
+ else sees it move smoothly.