summer-engine 3.0.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +27 -5
- package/.codex-plugin/plugin.json +28 -6
- package/.cursor-plugin/plugin.json +27 -5
- package/.factory-plugin/plugin.json +27 -5
- package/.opencode/plugins/summer.js +1 -1
- package/CHANGELOG.md +120 -0
- package/README.md +22 -7
- package/assets/audit/scene_audit.gd +4136 -0
- package/assets/seeing/seeing_probe.gd +1873 -0
- package/dist/cli/commands/setup.js +6 -19
- package/dist/cli/commands/skills.js +57 -32
- package/dist/core/api-client.d.ts +9 -1
- package/dist/core/api-client.js +21 -4
- package/dist/core/capabilities/agent-playbook.js +46 -0
- package/dist/core/capabilities/audit/accept.d.ts +55 -0
- package/dist/core/capabilities/audit/accept.js +147 -0
- package/dist/core/capabilities/audit/args.d.ts +95 -0
- package/dist/core/capabilities/audit/args.js +89 -0
- package/dist/core/capabilities/audit/audit.d.ts +56 -0
- package/dist/core/capabilities/audit/audit.js +287 -0
- package/dist/core/capabilities/audit/frame.d.ts +14 -0
- package/dist/core/capabilities/audit/frame.js +35 -0
- package/dist/core/capabilities/audit/gaps.d.ts +96 -0
- package/dist/core/capabilities/audit/gaps.js +257 -0
- package/dist/core/capabilities/audit/judge.d.ts +162 -0
- package/dist/core/capabilities/audit/judge.js +1134 -0
- package/dist/core/capabilities/audit/math.d.ts +110 -0
- package/dist/core/capabilities/audit/math.js +263 -0
- package/dist/core/capabilities/audit/summary.d.ts +74 -0
- package/dist/core/capabilities/audit/summary.js +212 -0
- package/dist/core/capabilities/board.d.ts +31 -0
- package/dist/core/capabilities/board.js +43 -0
- package/dist/core/capabilities/camera-view.d.ts +4 -2
- package/dist/core/capabilities/camera-view.js +6 -3
- package/dist/core/capabilities/connect-signal.d.ts +85 -0
- package/dist/core/capabilities/connect-signal.js +285 -0
- package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
- package/dist/core/capabilities/engine-fallbacks.js +5 -0
- package/dist/core/capabilities/engine-ops.d.ts +5 -1
- package/dist/core/capabilities/engine-ops.js +0 -3
- package/dist/core/capabilities/engine-receipt.d.ts +12 -0
- package/dist/core/capabilities/engine-receipt.js +26 -0
- package/dist/core/capabilities/file-read.d.ts +64 -0
- package/dist/core/capabilities/file-read.js +325 -0
- package/dist/core/capabilities/game-task-plan.js +4 -2
- package/dist/core/capabilities/grep.d.ts +60 -0
- package/dist/core/capabilities/grep.js +190 -0
- package/dist/core/capabilities/inspect-node.d.ts +56 -0
- package/dist/core/capabilities/inspect-node.js +225 -0
- package/dist/core/capabilities/inspect-resource.d.ts +61 -0
- package/dist/core/capabilities/inspect-resource.js +376 -0
- package/dist/core/capabilities/math3d.d.ts +28 -0
- package/dist/core/capabilities/math3d.js +88 -0
- package/dist/core/capabilities/motion-generation.d.ts +62 -0
- package/dist/core/capabilities/motion-generation.js +138 -0
- package/dist/core/capabilities/placement-batch.d.ts +102 -0
- package/dist/core/capabilities/placement-batch.js +483 -0
- package/dist/core/capabilities/placement-math.d.ts +70 -0
- package/dist/core/capabilities/placement-math.js +209 -0
- package/dist/core/capabilities/placement-script.d.ts +42 -0
- package/dist/core/capabilities/placement-script.js +1096 -0
- package/dist/core/capabilities/placement.d.ts +485 -0
- package/dist/core/capabilities/placement.js +1731 -0
- package/dist/core/capabilities/project-context.d.ts +33 -2
- package/dist/core/capabilities/project-context.js +87 -4
- package/dist/core/capabilities/replace-node.d.ts +91 -0
- package/dist/core/capabilities/replace-node.js +423 -0
- package/dist/core/capabilities/runtime-control.d.ts +20 -4
- package/dist/core/capabilities/runtime-control.js +67 -2
- package/dist/core/capabilities/scene-batch.d.ts +63 -0
- package/dist/core/capabilities/scene-batch.js +394 -0
- package/dist/core/capabilities/scene-readback.d.ts +36 -0
- package/dist/core/capabilities/scene-readback.js +54 -0
- package/dist/core/capabilities/seeing/args.d.ts +348 -0
- package/dist/core/capabilities/seeing/args.js +178 -0
- package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
- package/dist/core/capabilities/seeing/candidates.js +282 -0
- package/dist/core/capabilities/seeing/math.d.ts +134 -0
- package/dist/core/capabilities/seeing/math.js +269 -0
- package/dist/core/capabilities/seeing/probe.d.ts +62 -0
- package/dist/core/capabilities/seeing/probe.js +188 -0
- package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
- package/dist/core/capabilities/seeing/scoring.js +639 -0
- package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
- package/dist/core/capabilities/seeing/seeing.js +1341 -0
- package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
- package/dist/core/capabilities/seeing/shot-store.js +204 -0
- package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
- package/dist/core/capabilities/surface-snap-mesh.js +425 -0
- package/dist/core/capabilities/surface-snap.d.ts +77 -0
- package/dist/core/capabilities/surface-snap.js +461 -0
- package/dist/core/capabilities/tool-dispatch.js +231 -72
- package/dist/core/capabilities/tscn.d.ts +85 -0
- package/dist/core/capabilities/tscn.js +391 -0
- package/dist/core/capabilities/world-snapshot.d.ts +58 -0
- package/dist/core/capabilities/world-snapshot.js +150 -0
- package/dist/core/capability-skew.d.ts +5 -5
- package/dist/core/capability-skew.js +14 -6
- package/dist/core/headless/worker-engine-client.d.ts +1 -1
- package/dist/core/headless/worker-engine-client.js +2 -2
- package/dist/core/library-read.d.ts +37 -5
- package/dist/core/library-read.js +264 -33
- package/dist/core/library-search.d.ts +2 -2
- package/dist/core/skills-registry.d.ts +9 -1
- package/dist/core/skills-registry.js +25 -2
- package/dist/installer/agent-config.d.ts +9 -4
- package/dist/installer/agent-config.js +194 -392
- package/dist/installer/agent-table.d.ts +119 -0
- package/dist/installer/agent-table.js +619 -0
- package/dist/installer/setup.js +4 -2
- package/dist/installer/skill-locations.d.ts +8 -17
- package/dist/installer/skill-locations.js +22 -101
- package/dist/installer/version-check.d.ts +5 -1
- package/dist/installer/version-check.js +38 -28
- package/dist/mcp/server.js +9 -3
- package/dist/mcp/tools/asset-tools.js +21 -3
- package/dist/mcp/tools/audit-tools.d.ts +23 -0
- package/dist/mcp/tools/audit-tools.js +60 -0
- package/dist/mcp/tools/debug-tools.js +3 -1
- package/dist/mcp/tools/file-tools.js +17 -4
- package/dist/mcp/tools/generate-tools.js +74 -66
- package/dist/mcp/tools/library-tools.js +2 -0
- package/dist/mcp/tools/perception-tools.js +6 -19
- package/dist/mcp/tools/placement-tools.d.ts +24 -0
- package/dist/mcp/tools/placement-tools.js +91 -0
- package/dist/mcp/tools/project-tools.js +18 -15
- package/dist/mcp/tools/scene-tools.js +71 -83
- package/dist/mcp/tools/seeing-tools.d.ts +24 -0
- package/dist/mcp/tools/seeing-tools.js +64 -0
- package/dist/mcp/tools/spatial-tools.js +17 -9
- package/dist/mcp/tools/visual-tools.js +59 -7
- package/gemini-extension.json +26 -4
- package/integrations/README.md +48 -19
- package/integrations/amp/README.md +12 -0
- package/integrations/amp/manifest-target.json +3 -0
- package/integrations/antigravity/README.md +12 -0
- package/integrations/antigravity/manifest-target.json +3 -0
- package/integrations/claude-desktop/README.md +12 -0
- package/integrations/claude-desktop/manifest-target.json +3 -0
- package/integrations/cline/README.md +8 -9
- package/integrations/cline-cli/README.md +12 -0
- package/integrations/cline-cli/manifest-target.json +3 -0
- package/integrations/copilot-jetbrains/README.md +12 -0
- package/integrations/copilot-jetbrains/manifest-target.json +3 -0
- package/integrations/crush/README.md +12 -0
- package/integrations/crush/manifest-target.json +3 -0
- package/integrations/github-copilot/README.md +8 -8
- package/integrations/goose/README.md +12 -0
- package/integrations/goose/manifest-target.json +3 -0
- package/integrations/grok-build/README.md +12 -0
- package/integrations/grok-build/manifest-target.json +3 -0
- package/integrations/hermes/README.md +12 -0
- package/integrations/hermes/manifest-target.json +3 -0
- package/integrations/junie/README.md +12 -0
- package/integrations/junie/manifest-target.json +3 -0
- package/integrations/kilo-code/README.md +6 -10
- package/integrations/kimi-code/README.md +12 -0
- package/integrations/kimi-code/manifest-target.json +3 -0
- package/integrations/kiro/README.md +12 -0
- package/integrations/kiro/manifest-target.json +3 -0
- package/integrations/lm-studio/README.md +8 -8
- package/integrations/mistral-vibe/README.md +12 -0
- package/integrations/mistral-vibe/manifest-target.json +3 -0
- package/integrations/opencode/README.md +9 -12
- package/integrations/qoder/README.md +12 -0
- package/integrations/qoder/manifest-target.json +3 -0
- package/integrations/qwen-code/README.md +12 -0
- package/integrations/qwen-code/manifest-target.json +3 -0
- package/integrations/roo-code/README.md +8 -7
- package/integrations/rovo-dev/README.md +12 -0
- package/integrations/rovo-dev/manifest-target.json +3 -0
- package/integrations/trae/README.md +12 -0
- package/integrations/trae/manifest-target.json +3 -0
- package/integrations/visual-studio/README.md +12 -0
- package/integrations/visual-studio/manifest-target.json +3 -0
- package/integrations/vscode-copilot/README.md +9 -9
- package/integrations/warp/README.md +12 -0
- package/integrations/warp/manifest-target.json +3 -0
- package/integrations/windsurf/README.md +8 -9
- package/integrations/zed/README.md +12 -0
- package/integrations/zed/manifest-target.json +3 -0
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/references/summer-folder/resource.yaml +1 -1
- package/library/references/summer-folder/summer-folder.md +1 -1
- package/library/skills/3d-lighting/SKILL.md +1 -1
- package/library/skills/README.md +264 -0
- package/library/skills/adaptive-music/SKILL.md +1 -1
- package/library/skills/agent-playtesting/SKILL.md +1 -1
- package/library/skills/ai-characters-in-games/SKILL.md +220 -0
- package/library/skills/ai-characters-in-games/resource.yaml +30 -0
- package/library/skills/ambient-bed/SKILL.md +1 -1
- package/library/skills/animated-loop/SKILL.md +1 -1
- package/library/skills/animation-tree/SKILL.md +1 -1
- package/library/skills/art-direction/SKILL.md +1 -1
- package/library/skills/asset-strategy/SKILL.md +2 -1
- package/library/skills/asset-strategy/resource.yaml +2 -1
- package/library/skills/audio-direction/SKILL.md +1 -1
- package/library/skills/auto-fire-targeting/SKILL.md +1 -1
- package/library/skills/brainstorm-game/SKILL.md +1 -1
- package/library/skills/brainstorming/SKILL.md +1 -1
- package/library/skills/browse-templates/SKILL.md +3 -3
- package/library/skills/browse-templates/resource.yaml +1 -1
- package/library/skills/camera-rigs/SKILL.md +128 -0
- package/library/skills/camera-rigs/resource.yaml +29 -0
- package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
- package/library/skills/character-animation-wiring/SKILL.md +1 -1
- package/library/skills/character-model/SKILL.md +1 -1
- package/library/skills/character-movement/SKILL.md +326 -0
- package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
- package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
- package/library/skills/character-movement/references/movement-3d.md +136 -0
- package/library/skills/character-movement/references/platformer-feel.md +83 -0
- package/library/skills/character-movement/resource.yaml +40 -0
- package/library/skills/character-portrait/SKILL.md +1 -1
- package/library/skills/cinematic-cutscene/SKILL.md +1 -1
- package/library/skills/combat-basics/SKILL.md +159 -0
- package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
- package/library/skills/combat-basics/resource.yaml +34 -0
- package/library/skills/concept-art/SKILL.md +1 -1
- package/library/skills/create-asset-sheet/SKILL.md +1 -1
- package/library/skills/debug/SKILL.md +1 -1
- package/library/skills/debugging-game-feel/SKILL.md +1 -1
- package/library/skills/design-level/SKILL.md +1 -1
- package/library/skills/design-mechanic/SKILL.md +1 -1
- package/library/skills/design-npc/SKILL.md +1 -1
- package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
- package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
- package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
- package/library/skills/environment-kit/SKILL.md +1 -1
- package/library/skills/export-and-ship/SKILL.md +1 -1
- package/library/skills/fabricating-assets/SKILL.md +1 -1
- package/library/skills/facial-and-lipsync/SKILL.md +1 -1
- package/library/skills/fps-controller/SKILL.md +9 -7
- package/library/skills/fps-controller/resource.yaml +4 -1
- package/library/skills/game-feel/SKILL.md +1 -1
- package/library/skills/gameskill/SKILL.md +1 -1
- package/library/skills/gdscript-patterns/SKILL.md +1 -1
- package/library/skills/generate-motion/SKILL.md +9 -9
- package/library/skills/generate-motion/resource.yaml +2 -1
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
- package/library/skills/headless-scripting/SKILL.md +1 -1
- package/library/skills/in-game-purchases/SKILL.md +254 -0
- package/library/skills/in-game-purchases/resource.yaml +29 -0
- package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
- package/library/skills/investigating-bugs/SKILL.md +1 -1
- package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
- package/library/skills/make-game/SKILL.md +25 -3
- package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
- package/library/skills/make-game/references/2d-platformer.md +117 -0
- package/library/skills/make-game/references/2d-rpg-content.md +234 -0
- package/library/skills/make-game/references/2d-rpg.md +241 -0
- package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
- package/library/skills/make-game/references/2d-survivors.md +237 -0
- package/library/skills/make-game/references/3d-fps-systems.md +216 -0
- package/library/skills/make-game/references/3d-fps.md +177 -0
- package/library/skills/make-game/references/3d-horror-systems.md +186 -0
- package/library/skills/make-game/references/3d-horror.md +201 -0
- package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
- package/library/skills/make-game/references/3d-third-person.md +215 -0
- package/library/skills/make-game/resource.yaml +6 -1
- package/library/skills/multiplayer/SKILL.md +150 -0
- package/library/skills/multiplayer/resource.yaml +33 -0
- package/library/skills/multiplayer-movement/SKILL.md +510 -0
- package/library/skills/multiplayer-movement/files.md +501 -0
- package/library/skills/multiplayer-movement/resource.yaml +30 -0
- package/library/skills/multiplayer-project/SKILL.md +521 -0
- package/library/skills/multiplayer-project/files.md +448 -0
- package/library/skills/multiplayer-project/resource.yaml +36 -0
- package/library/skills/multiplayer-publish/SKILL.md +229 -0
- package/library/skills/multiplayer-publish/export-errors.md +89 -0
- package/library/skills/multiplayer-publish/resource.yaml +28 -0
- package/library/skills/multiplayer-state/SKILL.md +438 -0
- package/library/skills/multiplayer-state/files.md +592 -0
- package/library/skills/multiplayer-state/resource.yaml +35 -0
- package/library/skills/multiplayer-testing/SKILL.md +236 -0
- package/library/skills/multiplayer-testing/resource.yaml +39 -0
- package/library/skills/music-track/SKILL.md +1 -1
- package/library/skills/navigate-summer/SKILL.md +1 -1
- package/library/skills/new-project/SKILL.md +1 -1
- package/library/skills/organic-model/SKILL.md +1 -1
- package/library/skills/pixel-art/SKILL.md +1 -1
- package/library/skills/play/SKILL.md +1 -1
- package/library/skills/playtesting-a-feature/SKILL.md +1 -1
- package/library/skills/procedural-animation/SKILL.md +2 -2
- package/library/skills/procedural-animation/resource.yaml +1 -1
- package/library/skills/prop-model/SKILL.md +1 -1
- package/library/skills/psx-retro-rendering/SKILL.md +1 -1
- package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
- package/library/skills/remote-deploy/SKILL.md +1 -1
- package/library/skills/retarget/SKILL.md +1 -1
- package/library/skills/running-in-the-cloud/SKILL.md +1 -1
- package/library/skills/save-load/SKILL.md +156 -0
- package/library/skills/save-load/resource.yaml +27 -0
- package/library/skills/scene-composition/SKILL.md +1 -1
- package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
- package/library/skills/scene-scripting/SKILL.md +1 -1
- package/library/skills/scene-to-level/SKILL.md +1 -1
- package/library/skills/skill-create/SKILL.md +1 -1
- package/library/skills/skill-improve/SKILL.md +1 -1
- package/library/skills/skill-test/SKILL.md +1 -1
- package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
- package/library/skills/skybox-panorama/SKILL.md +1 -1
- package/library/skills/sound-effect/SKILL.md +1 -1
- package/library/skills/spatial-placement/SKILL.md +134 -3
- package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
- package/library/skills/spatial-placement/resource.yaml +16 -2
- package/library/skills/sprite-sheet/SKILL.md +1 -1
- package/library/skills/summer-analytics/SKILL.md +147 -0
- package/library/skills/summer-analytics/resource.yaml +28 -0
- package/library/skills/summer-friends/SKILL.md +226 -0
- package/library/skills/summer-friends/resource.yaml +28 -0
- package/library/skills/summer-leaderboards/SKILL.md +231 -0
- package/library/skills/summer-leaderboards/resource.yaml +30 -0
- package/library/skills/summer-match-results/SKILL.md +286 -0
- package/library/skills/summer-match-results/resource.yaml +32 -0
- package/library/skills/summer-matchmaking/SKILL.md +301 -0
- package/library/skills/summer-matchmaking/resource.yaml +32 -0
- package/library/skills/summer-parties/SKILL.md +253 -0
- package/library/skills/summer-parties/resource.yaml +30 -0
- package/library/skills/summer-player-data/SKILL.md +322 -0
- package/library/skills/summer-player-data/resource.yaml +30 -0
- package/library/skills/summer-store/SKILL.md +271 -0
- package/library/skills/summer-store/resource.yaml +29 -0
- package/library/skills/summer-world-chat/SKILL.md +195 -0
- package/library/skills/summer-world-chat/resource.yaml +30 -0
- package/library/skills/summer-world-saves/SKILL.md +284 -0
- package/library/skills/summer-world-saves/resource.yaml +29 -0
- package/library/skills/text-to-motion/SKILL.md +99 -0
- package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
- package/library/skills/text-to-motion/resource.yaml +41 -0
- package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
- package/library/skills/tileable-texture/SKILL.md +1 -1
- package/library/skills/trailer-shot/SKILL.md +1 -1
- package/library/skills/tune-performance/SKILL.md +1 -1
- package/library/skills/ui-basics/SKILL.md +10 -1
- package/library/skills/ui-graphics/SKILL.md +1 -1
- package/library/skills/use-widget-asset/SKILL.md +1 -1
- package/library/skills/using-summer/SKILL.md +2 -2
- package/library/skills/using-summer/resource.yaml +2 -2
- package/library/skills/vehicle-model/SKILL.md +1 -1
- package/library/skills/verification-before-completion/SKILL.md +1 -1
- package/library/skills/verifying-scenes/SKILL.md +76 -2
- package/library/skills/verifying-scenes/resource.yaml +13 -2
- package/library/skills/vfx-dissolve/SKILL.md +1 -1
- package/library/skills/vfx-fire/SKILL.md +1 -1
- package/library/skills/vfx-hit-spark/SKILL.md +1 -1
- package/library/skills/vfx-lightning/SKILL.md +1 -1
- package/library/skills/vfx-magic-glow/SKILL.md +1 -1
- package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
- package/library/skills/vfx-smoke/SKILL.md +1 -1
- package/library/skills/vfx-water-ripple/SKILL.md +1 -1
- package/library/skills/voice-line/SKILL.md +1 -1
- package/library/skills/web-and-touch-input/SKILL.md +38 -0
- package/library/skills/web-and-touch-input/resource.yaml +28 -0
- package/library/skills/web-compatibility-look/SKILL.md +62 -0
- package/library/skills/web-compatibility-look/resource.yaml +30 -0
- package/library/skills/world-building-3d/SKILL.md +8 -1
- package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
- package/library/skills/world-building-3d/resource.yaml +2 -1
- package/library/skills/writing-plans/SKILL.md +1 -1
- package/library/skills/writing-skills/SKILL.md +1 -1
- package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
- package/library/tools/attach-to-surface/resource.yaml +142 -0
- package/library/tools/batch/resource.yaml +9 -3
- package/library/tools/connect-ports/resource.yaml +120 -0
- package/library/tools/connect-signal/resource.yaml +3 -2
- package/library/tools/debug-views/resource.yaml +94 -0
- package/library/tools/frame-nodes/resource.yaml +104 -0
- package/library/tools/frame-shot/resource.yaml +134 -0
- package/library/tools/generate-motion/resource.yaml +44 -9
- package/library/tools/get-board/resource.yaml +50 -0
- package/library/tools/get-project-context/resource.yaml +13 -2
- package/library/tools/grep/resource.yaml +77 -0
- package/library/tools/inspect-asset/resource.yaml +71 -0
- package/library/tools/inspect-node/resource.yaml +9 -2
- package/library/tools/inspect-resource/resource.yaml +16 -5
- package/library/tools/instantiate-scene/resource.yaml +27 -2
- package/library/tools/measure/resource.yaml +96 -0
- package/library/tools/place-adjacent/resource.yaml +113 -0
- package/library/tools/play/resource.yaml +15 -2
- package/library/tools/raycast/resource.yaml +101 -0
- package/library/tools/read-file/resource.yaml +36 -2
- package/library/tools/read-library/resource.yaml +2 -2
- package/library/tools/repeat-along/resource.yaml +129 -0
- package/library/tools/replace-node/resource.yaml +11 -5
- package/library/tools/scene-audit/resource.yaml +144 -0
- package/library/tools/screenshot/resource.yaml +13 -2
- package/library/tools/search-assets/resource.yaml +18 -0
- package/library/tools/shot-sheet/resource.yaml +110 -0
- package/library/tools/snap-to-surface/resource.yaml +4 -1
- package/library/tools/world-snapshot/resource.yaml +24 -3
- package/library/tools/zoom/resource.yaml +105 -0
- package/package.json +3 -3
- package/registry/generated/aliases.json +17 -3
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +26 -4
- package/registry/generated/index.json +2154 -469
- package/registry/generated/marketplace.claude.json +2 -2
- package/registry/generated/plugin.claude.json +27 -5
- package/registry/generated/plugin.codex.json +28 -6
- package/registry/generated/plugin.cursor.json +27 -5
- package/registry/generated/plugin.factory.json +27 -5
- package/registry/generated/skills-index.md +264 -0
- package/registry/generated/skills-registry.json +901 -206
- package/registry/generated/templates-registry.json +2 -2
- package/library/skills/host-authoritative-state/SKILL.md +0 -332
- package/library/skills/host-authoritative-state/resource.yaml +0 -28
- package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
- package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
- package/library/skills/setup-multiplayer/SKILL.md +0 -336
- package/library/skills/setup-multiplayer/resource.yaml +0 -28
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# 3D Third-Person - Systems
|
|
2
|
+
|
|
3
|
+
The combat and content layer on top of `3d-third-person.md`: melee, bullets,
|
|
4
|
+
grenade with arc preview, two enemy archetypes, coins, destructible boxes,
|
|
5
|
+
and the HUD.
|
|
6
|
+
|
|
7
|
+
## Shared damage interface
|
|
8
|
+
|
|
9
|
+
Everything hittable (player, enemies, boxes) implements:
|
|
10
|
+
|
|
11
|
+
```gdscript
|
|
12
|
+
func damage(impact_point: Vector3, force: Vector3) -> void
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
and joins the "damageables" group. `impact_point` is
|
|
16
|
+
`global_position - body.global_position` (direction from body to impact),
|
|
17
|
+
`force` is the knockback vector. Enemies additionally join "targeteables"
|
|
18
|
+
for grenade lock-on. One interface, three weapons, all content - keep it.
|
|
19
|
+
|
|
20
|
+
## Weapons
|
|
21
|
+
|
|
22
|
+
Tab toggles DEFAULT and GRENADE (a `weapon_switched` signal drives the HUD
|
|
23
|
+
icons). DEFAULT: left-click = melee from the hip, aim (RMB) + left-click =
|
|
24
|
+
ranged shot with over-shoulder camera + crosshair. GRENADE: left-click
|
|
25
|
+
throws with a live arc preview.
|
|
26
|
+
|
|
27
|
+
### Melee (animation-gated hitbox)
|
|
28
|
+
|
|
29
|
+
The MeleeAttackArea's CollisionShape3D starts disabled. The "Attack"
|
|
30
|
+
animation (0.3-0.5s) has method-call tracks: `activate()` at the impact
|
|
31
|
+
frame (~0.15s), `deactivate()` at the end. The area's `body_entered` damages
|
|
32
|
+
"damageables" with force pointing away from the player. Player side:
|
|
33
|
+
`attack()` plays the animation, fires the skin's punch OneShot, and sets
|
|
34
|
+
`velocity = rotation_root.basis * Vector3.BACK * attack_impulse` (forward
|
|
35
|
+
lunge). Movement is locked while the attack animation plays.
|
|
36
|
+
|
|
37
|
+
Animation-gated hitboxes beat timer-gated ones: the active window is
|
|
38
|
+
authored visually next to the swing frames.
|
|
39
|
+
|
|
40
|
+
### Bullet (shared by player AND enemies)
|
|
41
|
+
|
|
42
|
+
Node3D moved manually in `_process` - no physics body:
|
|
43
|
+
|
|
44
|
+
```gdscript
|
|
45
|
+
func _ready() -> void:
|
|
46
|
+
_area.body_entered.connect(_on_body_entered)
|
|
47
|
+
look_at(global_position + velocity)
|
|
48
|
+
_alive_limit = distance_limit / velocity.length()
|
|
49
|
+
|
|
50
|
+
func _process(delta: float) -> void:
|
|
51
|
+
global_position += velocity * delta
|
|
52
|
+
_time_alive += delta
|
|
53
|
+
_bullet_visuals.scale = Vector3.ONE * scale_decay.sample(_time_alive / _alive_limit)
|
|
54
|
+
if _time_alive > _alive_limit:
|
|
55
|
+
queue_free()
|
|
56
|
+
|
|
57
|
+
func _on_body_entered(body: Node3D) -> void:
|
|
58
|
+
if body == shooter:
|
|
59
|
+
return
|
|
60
|
+
if body.is_in_group("damageables"):
|
|
61
|
+
body.damage(global_position - body.global_position, velocity)
|
|
62
|
+
queue_free()
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The `shooter` reference prevents self-hits, which is what lets one bullet
|
|
66
|
+
scene serve both sides. Distance limit expressed as time
|
|
67
|
+
(`distance / speed`); visual scale decays via an exported Curve so bullets
|
|
68
|
+
fade with range. Player shots originate at `global_position + Vector3.UP`
|
|
69
|
+
and fly toward `camera_controller.get_aim_target()`.
|
|
70
|
+
|
|
71
|
+
Fast projectiles tunnel through thin walls: keep speeds moderate (player
|
|
72
|
+
10, enemies 6) or fatten the Area3D shape.
|
|
73
|
+
|
|
74
|
+
### Grenade launcher (arc preview + lock-on)
|
|
75
|
+
|
|
76
|
+
While GRENADE is equipped the launcher is visible and every physics frame:
|
|
77
|
+
camera tilt lerps throw distance between min 7 and max 16; a ShapeCast3D
|
|
78
|
+
finds the landing point; if the cast hits a "targeteables" body, the landing
|
|
79
|
+
snaps to that enemy (lock-on, SnapMesh indicator); initial velocity
|
|
80
|
+
decomposes into vertical `sqrt(2 * gravity * peak_height)` and horizontal
|
|
81
|
+
`distance / time_to_land`; the preview trail is a triangle-strip mesh built
|
|
82
|
+
with SurfaceTool sampling the parabola at 0.05s steps.
|
|
83
|
+
|
|
84
|
+
The grenade itself is a CharacterBody3D using `move_and_collide` (NOT
|
|
85
|
+
move_and_slide) so it can bounce:
|
|
86
|
+
|
|
87
|
+
```gdscript
|
|
88
|
+
func _physics_process(delta) -> void:
|
|
89
|
+
_velocity += Vector3.DOWN * gravity * delta
|
|
90
|
+
var collision := move_and_collide(_velocity * delta)
|
|
91
|
+
if collision:
|
|
92
|
+
_velocity = _velocity.bounce(collision.get_normal(0)) * 0.7
|
|
93
|
+
if _explosion_start_timer.is_stopped():
|
|
94
|
+
_explosion_start_timer.start()
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
First bounce arms the fuse timer. Explosion: damage all overlapping
|
|
98
|
+
"damageables" in the ExplosionArea EXCEPT the Player (`not body is Player` -
|
|
99
|
+
self-immunity), spawn explosion visuals, hide, await the sound, free. On
|
|
100
|
+
throw, add a collision exception between grenade and thrower via
|
|
101
|
+
`PhysicsServer3D.body_add_collision_exception`.
|
|
102
|
+
|
|
103
|
+
## Enemies
|
|
104
|
+
|
|
105
|
+
Both are RigidBody3D with a PlayerDetectionArea (big sphere Area3D), a
|
|
106
|
+
reaction label ("!" / "?" animations on detect/lose), and the same death
|
|
107
|
+
choreography: play defeat sound, set `_alive = false`, DISCONNECT the
|
|
108
|
+
detection signals (dead enemies must not react), enable the death collider,
|
|
109
|
+
enable gravity so the body drops, wait 2s, spawn a smoke puff, `await
|
|
110
|
+
puff.full`, burst coins out of the smoke, `queue_free()`.
|
|
111
|
+
|
|
112
|
+
The smoke puff emits `full` from an animation keyframe at peak opacity -
|
|
113
|
+
awaiting it makes coins appear to burst out of the cloud instead of
|
|
114
|
+
clipping through a half-formed puff.
|
|
115
|
+
|
|
116
|
+
### Bee bot (flying turret)
|
|
117
|
+
|
|
118
|
+
RigidBody3D with `gravity_scale = 0` (floats). While a target is set:
|
|
119
|
+
|
|
120
|
+
```gdscript
|
|
121
|
+
var target_transform := transform.looking_at(_target.global_position)
|
|
122
|
+
transform = transform.interpolate_with(target_transform, 0.1)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Fires the SAME bullet scene as the player every 1.5s at speed 6, aimed at
|
|
126
|
+
`target.global_position + Vector3.UP`. `damage()` applies an impulse
|
|
127
|
+
(clamped length 3) then runs the death choreography; gravity_scale flips to
|
|
128
|
+
1.0 so it falls out of the air.
|
|
129
|
+
|
|
130
|
+
### Beetle bot (NavigationAgent3D chaser)
|
|
131
|
+
|
|
132
|
+
RigidBody3D with rotation axes locked (rigid until death). Chase loop:
|
|
133
|
+
|
|
134
|
+
```gdscript
|
|
135
|
+
_navigation_agent.target_position = _target.global_position
|
|
136
|
+
var next := _navigation_agent.get_next_path_position()
|
|
137
|
+
if not _navigation_agent.is_target_reached():
|
|
138
|
+
var direction := (next - global_position)
|
|
139
|
+
direction.y = 0 # never dive/fly
|
|
140
|
+
direction = direction.normalized()
|
|
141
|
+
var collision := move_and_collide(direction * delta * 3)
|
|
142
|
+
if collision and collision.get_collider() is Player:
|
|
143
|
+
var force := -(global_position - collider.global_position)
|
|
144
|
+
force.y = 0.5
|
|
145
|
+
collider.damage(impact_point, force * 10.0)
|
|
146
|
+
_beetle_skin.attack()
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`look_at` the target with Y flattened to its own height. On death, unlock
|
|
150
|
+
all angular axes so the corpse tumbles.
|
|
151
|
+
|
|
152
|
+
Navigation requirements: the level MUST have a baked NavigationRegion3D or
|
|
153
|
+
the beetle stands still forever; the target must be reachable on the
|
|
154
|
+
navmesh; always zero the Y of path directions.
|
|
155
|
+
|
|
156
|
+
Enemy skins: AnimationTree state machines (Idle/Walk/Attack/Shake/PowerOff)
|
|
157
|
+
with a secondary-action timer firing random idle shakes every 3-8s;
|
|
158
|
+
`power_off()` stops that timer.
|
|
159
|
+
|
|
160
|
+
## Coins
|
|
161
|
+
|
|
162
|
+
RigidBody3D collectible, either placed in the level or scattered by
|
|
163
|
+
`spawn()` (random impulse: direction rotated randomly around UP, range 2-4,
|
|
164
|
+
height 1-3). Collection is DELAYED: layer 3 collision is off for
|
|
165
|
+
`coin_delay` (0.5s default, 1.5s when the player drops them) so coins from
|
|
166
|
+
a kill do not vacuum back instantly.
|
|
167
|
+
|
|
168
|
+
Magnet: when the player enters the coin's detection area (mask = Player
|
|
169
|
+
layer 4), freeze physics and tween to the player:
|
|
170
|
+
|
|
171
|
+
```gdscript
|
|
172
|
+
func set_target(new_target: PhysicsBody3D) -> void:
|
|
173
|
+
PhysicsServer3D.body_add_collision_exception(get_rid(), new_target.get_rid())
|
|
174
|
+
if _target == null:
|
|
175
|
+
sleeping = true
|
|
176
|
+
freeze = true
|
|
177
|
+
_initial_tween_position = global_position
|
|
178
|
+
_target = new_target
|
|
179
|
+
var tween := create_tween()
|
|
180
|
+
tween.tween_method(_follow, 0.0, 1.0, 0.5) # lerp start -> player
|
|
181
|
+
tween.tween_callback(_collect)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`_follow` lerps from the captured start to the LIVE player position, so the
|
|
185
|
+
coin homes even while the player runs. Collect: random-pitch sound,
|
|
186
|
+
`player.collect_coin()`, hide, await audio, free. Coin model: spin
|
|
187
|
+
`rotation.y += 1.5 * delta`, bob `sin(t) * 0.04`.
|
|
188
|
+
|
|
189
|
+
## Destructible boxes
|
|
190
|
+
|
|
191
|
+
`damage()` on the box: spawn 5 coins with `spawn()`, instantiate a
|
|
192
|
+
pre-fractured debris scene, disable own collision (deferred), play sound,
|
|
193
|
+
await it, free. Debris scene = 6 hidden frozen RigidBody3D pieces; on ready,
|
|
194
|
+
shuffle and launch 3 random ones with `apply_force(rand_vector * 500)`,
|
|
195
|
+
leave the rest hidden. Half-count random debris looks as good as full
|
|
196
|
+
simulation at a fraction of the cost.
|
|
197
|
+
|
|
198
|
+
## HUD
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
UI (CanvasLayer)
|
|
202
|
+
AimRecticle (%unique, ColorRect centered) # visible only while aiming
|
|
203
|
+
CoinsContainer (%unique, HBoxContainer) # slides in on change
|
|
204
|
+
CoinIcon + CoinsLabel + Timer
|
|
205
|
+
WeaponUI (PanelContainer) # Flash / Grenade icons
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Coin counter: slides from y -100 to y 20 on `update_coins_amount`, restarts
|
|
209
|
+
its display timer per change, slides back out on timeout. Weapon icons:
|
|
210
|
+
inactive at alpha 0.2, tween to full white on select; `switch_to()` guards
|
|
211
|
+
against reselecting the current one. Use unique names (%) so the deep
|
|
212
|
+
player script reaches UI without brittle paths.
|
|
213
|
+
|
|
214
|
+
## Order of work
|
|
215
|
+
|
|
216
|
+
1. Melee: attack animation + gated hitbox + a destructible box to punch.
|
|
217
|
+
2. Coins with magnet + HUD counter (the reward loop).
|
|
218
|
+
3. Aim mode: over-shoulder pivot + crosshair + bullet.
|
|
219
|
+
4. Bee bot (reuses your bullet), then beetle bot (navmesh required).
|
|
220
|
+
5. Grenade launcher last - arc preview, lock-on, explosion.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# 3D Third-Person - Core
|
|
2
|
+
|
|
3
|
+
Third-person action blueprint: camera-relative movement, orbit camera with
|
|
4
|
+
SpringArm3D and over-shoulder aim pivot, animation-driven character skin, and
|
|
5
|
+
level assembly. Combat, enemies, collectibles, and HUD live in
|
|
6
|
+
`3d-third-person-systems.md`.
|
|
7
|
+
|
|
8
|
+
## Minimum playable base (build this first)
|
|
9
|
+
|
|
10
|
+
Level (CSG floor + light + WorldEnvironment) + player capsule with
|
|
11
|
+
camera-relative WASD, orbit camera on a SpringArm3D, and jump. Prove "run
|
|
12
|
+
around, camera orbits, no wall clipping" before combat exists.
|
|
13
|
+
|
|
14
|
+
## Player scene tree
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
Player (CharacterBody3D)
|
|
18
|
+
CharacterRotationRoot (Node3D) # model rotation lives here, not on body
|
|
19
|
+
CharacterSkin (Node3D) # mesh + AnimationTree
|
|
20
|
+
MeleeAnchor (Node3D)
|
|
21
|
+
AnimationPlayer # "Attack" anim toggles hitbox
|
|
22
|
+
MeleeAttackArea (Area3D + CollisionShape3D, disabled)
|
|
23
|
+
CameraController (Node3D) # follows via code, NOT rigid parenting
|
|
24
|
+
CameraSpringArm (SpringArm3D)
|
|
25
|
+
CameraThirdPersonPivot (Node3D)
|
|
26
|
+
CameraOverShoulderPivot (Node3D) # right + closer, for aiming
|
|
27
|
+
PlayerCamera (Camera3D)
|
|
28
|
+
CameraRayCast (RayCast3D, target (0,0,-100)) # aim target
|
|
29
|
+
GrenadeLauncher (Node3D) # LaunchPoint, ShapeCast3D, TrailMesh
|
|
30
|
+
GroundShapeCast (ShapeCast3D, down) # ground height for camera
|
|
31
|
+
StepSound / LandingSound (AudioStreamPlayer3D)
|
|
32
|
+
UI (CanvasLayer) # %AimRecticle, %CoinsContainer, WeaponUI
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Physics layers: 1 Entities, 2 Level, 3 Coins, 4 Player. Groups: "damageables"
|
|
36
|
+
(anything with `damage()`), "targeteables" (grenade lock-on).
|
|
37
|
+
|
|
38
|
+
Input: move_up/down/left/right, jump (Space, hold for air boost), attack
|
|
39
|
+
(LMB / RT), aim (RMB / LT), swap_weapons (Tab), pause, camera_left/right/up/
|
|
40
|
+
down (QERF keyboard fallback + right stick). The player script can
|
|
41
|
+
auto-register missing actions at runtime via `InputMap.add_action` so the
|
|
42
|
+
scene works when dropped into a bare project.
|
|
43
|
+
|
|
44
|
+
## Controller: the decisions that matter
|
|
45
|
+
|
|
46
|
+
Tuning baseline: move_speed 8.0, acceleration 4.0, rotation_speed 12.0,
|
|
47
|
+
jump_initial_impulse 12.0, jump_additional_force 4.5 (held-jump air boost),
|
|
48
|
+
attack_impulse 10.0, gravity -30.0 (deliberately NOT project default;
|
|
49
|
+
project gravity 16 is too floaty for 3D platforming - tune independently).
|
|
50
|
+
|
|
51
|
+
Camera-relative input with diagonal correction:
|
|
52
|
+
|
|
53
|
+
```gdscript
|
|
54
|
+
func _get_camera_oriented_input() -> Vector3:
|
|
55
|
+
if _attack_animation_player.is_playing():
|
|
56
|
+
return Vector3.ZERO # attacking locks movement
|
|
57
|
+
var raw := Input.get_vector("move_left", "move_right", "move_up", "move_down")
|
|
58
|
+
var input := Vector3.ZERO
|
|
59
|
+
input.x = -raw.x * sqrt(1.0 - raw.y * raw.y / 2.0) # no faster diagonals
|
|
60
|
+
input.z = -raw.y * sqrt(1.0 - raw.x * raw.x / 2.0)
|
|
61
|
+
input = _camera_controller.global_transform.basis * input
|
|
62
|
+
input.y = 0.0
|
|
63
|
+
return input
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Last strong direction - the model holds its facing when input stops instead
|
|
67
|
+
of snapping to zero; while aiming it faces camera-forward:
|
|
68
|
+
|
|
69
|
+
```gdscript
|
|
70
|
+
if _move_direction.length() > 0.2:
|
|
71
|
+
_last_strong_direction = _move_direction.normalized()
|
|
72
|
+
if is_aiming:
|
|
73
|
+
_last_strong_direction = (_camera_controller.global_transform.basis * Vector3.BACK).normalized()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Orientation slerps `CharacterRotationRoot` (never the body) toward that
|
|
77
|
+
direction at rotation_speed, preserving model scale.
|
|
78
|
+
|
|
79
|
+
Velocity: split Y off before lerping so gravity is never interpolated:
|
|
80
|
+
|
|
81
|
+
```gdscript
|
|
82
|
+
var y_velocity := velocity.y
|
|
83
|
+
velocity.y = 0.0
|
|
84
|
+
velocity = velocity.lerp(_move_direction * move_speed, acceleration * delta)
|
|
85
|
+
if _move_direction.length() == 0 and velocity.length() < stopping_speed:
|
|
86
|
+
velocity = Vector3.ZERO
|
|
87
|
+
velocity.y = y_velocity
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Jump: impulse on press, plus `jump_additional_force * delta` while jump is
|
|
91
|
+
held and still rising (variable height). Track `_is_on_floor_buffer` to
|
|
92
|
+
detect the landing frame for the landing sound.
|
|
93
|
+
|
|
94
|
+
Unstick hack after `move_and_slide()`: if velocity is nonzero but position
|
|
95
|
+
did not change (wedged in geometry), nudge
|
|
96
|
+
`global_position += get_wall_normal() * 0.1`.
|
|
97
|
+
|
|
98
|
+
`damage(impact_point, force)` on the player: force.y forced positive (always
|
|
99
|
+
tossed upward), clamped by max_throwback_force 15, drops up to 5 coins that
|
|
100
|
+
scatter for re-collection.
|
|
101
|
+
|
|
102
|
+
## Camera system
|
|
103
|
+
|
|
104
|
+
Two pivots, one camera. `CameraThirdPersonPivot` sits at the end of the
|
|
105
|
+
SpringArm3D (behind and above). `CameraOverShoulderPivot` is a plain Node3D
|
|
106
|
+
offset right and closer (about x 1.0, y 0.5, z -2.0). Aiming switches pivots
|
|
107
|
+
via `set_pivot()`; each `_process` the camera copies the active pivot's
|
|
108
|
+
global transform and zeroes `rotation.z`.
|
|
109
|
+
|
|
110
|
+
- Orbit uses accumulated euler angles from mouse (`_unhandled_input`, only
|
|
111
|
+
while mouse captured) plus joystick strength added in `_process`; inputs
|
|
112
|
+
are consumed and zeroed every frame. Tilt clamped -60..60 deg. Never
|
|
113
|
+
`look_at()` per frame - it jitters.
|
|
114
|
+
- SpringArm3D handles wall avoidance for free, but MUST exclude the player:
|
|
115
|
+
`_camera_spring_arm.add_excluded_object(anchor.get_rid())` and
|
|
116
|
+
`_camera_raycast.add_exception_rid(anchor.get_rid())` in `setup()`.
|
|
117
|
+
- Ground-height tracking: camera Y lerps toward the player's
|
|
118
|
+
`_ground_height` (from GroundShapeCast), not the player's Y - so jumps do
|
|
119
|
+
not bounce the camera. The player computes `_ground_height` as the max
|
|
120
|
+
collision point of the downward ShapeCast, clamped to its own Y when
|
|
121
|
+
falling below it.
|
|
122
|
+
- Aim target: CameraRayCast collision point (or the ray end if no hit) is
|
|
123
|
+
what bullets fly toward and what the grenade locks onto -
|
|
124
|
+
`get_aim_target()` / `get_aim_collider()`.
|
|
125
|
+
|
|
126
|
+
## Character skin (AnimationTree)
|
|
127
|
+
|
|
128
|
+
If the visual is a Summer humanoid package, do not use the generic setup below.
|
|
129
|
+
Instantiate its `character.tscn` under `CharacterRotationRoot`, preserve the package's
|
|
130
|
+
normalized `-Z` forward axis, then install the `character-movement` skill's
|
|
131
|
+
`../../character-movement/references/default-third-person-controller.gd` unchanged for the standard
|
|
132
|
+
playable controller (that skill has the byte-exact install steps and the
|
|
133
|
+
verification probe). Do not hand-write an equivalent controller. Never rebuild package clips
|
|
134
|
+
into a second AnimationTree.
|
|
135
|
+
|
|
136
|
+
The generic setup below is only for non-package character skins that already expose
|
|
137
|
+
compatible animations.
|
|
138
|
+
|
|
139
|
+
BlendTree root: a StateMachine (idle / move / jump / fall, where move is a
|
|
140
|
+
BlendSpace1D walk-run blended by normalized speed) plus a PunchOneShot
|
|
141
|
+
(AnimationNodeOneShot) layered on top so punches play over any state.
|
|
142
|
+
|
|
143
|
+
```gdscript
|
|
144
|
+
func set_moving(value: bool): # SETTER - travel only on change
|
|
145
|
+
moving = value
|
|
146
|
+
state_machine.travel("move" if moving else "idle")
|
|
147
|
+
|
|
148
|
+
func punch():
|
|
149
|
+
animation_tree["parameters/PunchOneShot/request"] = AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Driving rules from the player: `jump()` on jump press, `fall()` when
|
|
153
|
+
`not is_on_floor() and velocity.y < 0`, `set_moving(xz_speed > stopping_speed)`
|
|
154
|
+
plus `set_moving_speed(inverse_lerp(0, move_speed, xz_speed))` on the floor.
|
|
155
|
+
|
|
156
|
+
Footsteps: a `stepped` signal emitted from method-call keyframes in the
|
|
157
|
+
walk/run animations; player plays the step sound with `randfn(1.2, 0.2)`
|
|
158
|
+
pitch. Free audio sync, no timers.
|
|
159
|
+
|
|
160
|
+
`animation_tree.active = true` in `_ready()` or nothing plays. Imported
|
|
161
|
+
animations often default to non-looping: keep a `_force_loop` export array
|
|
162
|
+
and set `loop_mode = Animation.LOOP_LINEAR` on those at runtime.
|
|
163
|
+
|
|
164
|
+
## Level assembly
|
|
165
|
+
|
|
166
|
+
Check for real assets first (`asset-strategy`: `summer_search_assets`, then
|
|
167
|
+
`summer_import_asset`): a ready location or kit beats CSG. Keep CSG for the
|
|
168
|
+
first-motion blockout, invisible glue (death planes, triggers) and pieces no
|
|
169
|
+
asset covers — do not ship a grey-box level when a real one is available.
|
|
170
|
+
|
|
171
|
+
- WorldEnvironment: sky background (ProceduralSkyMaterial), ACES tonemap
|
|
172
|
+
(`tonemap_mode = 2`), glow enabled. Without WorldEnvironment everything
|
|
173
|
+
is flat and dark.
|
|
174
|
+
- DirectionalLight3D angled ~45 deg, `shadow_enabled = true` (off by
|
|
175
|
+
default; without shadows objects float).
|
|
176
|
+
- Geometry: CSGCombiner3D with `use_collision = true`, CSGBox3D/
|
|
177
|
+
CSGCylinder3D children; boolean subtraction (operation 2) for tunnels.
|
|
178
|
+
Materials with `uv1_triplanar = true` so textures map on any face.
|
|
179
|
+
- DeathPlane: big Area3D at y -20; `body_entered` on the Player calls
|
|
180
|
+
`reset_position()` (respawn at `_start_position` captured in `_ready`).
|
|
181
|
+
- Jump pad: Area3D setting
|
|
182
|
+
`body.velocity = Vector3.UP * body.jump_initial_impulse + transform.basis * Vector3.UP * impulse_strength`
|
|
183
|
+
(basis-relative so rotated pads launch at angles) + squash-and-elastic
|
|
184
|
+
rebound tween on the mesh.
|
|
185
|
+
- Project: 1920x1080, stretch canvas_items / keep_height.
|
|
186
|
+
- Pause menu node needs `process_mode = ALWAYS` and must flip mouse mode
|
|
187
|
+
between CAPTURED (gameplay) and VISIBLE (menu).
|
|
188
|
+
|
|
189
|
+
## Build order
|
|
190
|
+
|
|
191
|
+
1. Project settings + input actions + layer names.
|
|
192
|
+
2. Player scene tree above; movement + jump with a placeholder capsule.
|
|
193
|
+
3. CameraController: spring arm orbit, then over-shoulder aim pivot.
|
|
194
|
+
4. CharacterSkin AnimationTree once movement feels right.
|
|
195
|
+
5. Level: imported location/props (`asset-strategy`) where they fit;
|
|
196
|
+
CSG floor/platforms only as blockout or for missing pieces; light,
|
|
197
|
+
environment, death plane, jump pad.
|
|
198
|
+
6. Combat + enemies + coins (`3d-third-person-systems.md`).
|
|
199
|
+
|
|
200
|
+
## Traps
|
|
201
|
+
|
|
202
|
+
- Parenting the camera rigidly to the player - it inherits every rotation
|
|
203
|
+
and nauseates. Follow via code with offset + lerp.
|
|
204
|
+
- Skipping SpringArm3D (camera clips walls) or forgetting to exclude the
|
|
205
|
+
player's RID from it (camera collides with the player).
|
|
206
|
+
- `look_at()` every frame for camera or `state_machine.travel()` every
|
|
207
|
+
frame for animation - both jitter/reset; only act on change.
|
|
208
|
+
- Scaling the CharacterBody3D itself - scale the mesh under
|
|
209
|
+
CharacterRotationRoot. Physics on scaled bodies misbehaves.
|
|
210
|
+
- 1 unit = 1 meter. Characters are 1-2 units tall; extreme scales break
|
|
211
|
+
physics and lighting.
|
|
212
|
+
- Toggling CollisionShape3D `disabled` directly inside physics callbacks -
|
|
213
|
+
always `set_deferred("disabled", ...)`.
|
|
214
|
+
- Low gravity. -30 for the player feels right; project-default 16 is
|
|
215
|
+
floaty. Tune player gravity independently of the physics setting.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
id: skill/make-game
|
|
2
2
|
kind: skill
|
|
3
|
-
version: 1.0
|
|
3
|
+
version: 1.1.0
|
|
4
4
|
summary: "Orchestration spine for 'make me a game': brainstorm, plan, scaffold, mechanics, art, audio, polish, verify, ship — delegates to specialist skills."
|
|
5
5
|
use_when:
|
|
6
6
|
- the user says 'make me a game', 'build me a game', 'I want to make a [genre] game', or 'let's build something' — running the full game-dev pipeline
|
|
7
7
|
- the user wants a complete playable game end to end, from brainstorm through shipping
|
|
8
|
+
- the user names a genre — platformer, survivors, top-down RPG, FPS, third-person, horror — and the build needs its architecture and build order
|
|
8
9
|
facets:
|
|
9
10
|
lifecycle:
|
|
10
11
|
- build
|
|
@@ -27,6 +28,10 @@ related:
|
|
|
27
28
|
- skill/new-project
|
|
28
29
|
- skill/play
|
|
29
30
|
- skill/scene-composition
|
|
31
|
+
- skill/character-movement
|
|
32
|
+
- skill/camera-rigs
|
|
33
|
+
- skill/combat-basics
|
|
34
|
+
- skill/save-load
|
|
30
35
|
source: official
|
|
31
36
|
license: MIT
|
|
32
37
|
status: stable
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: multiplayer
|
|
3
|
+
description: "Start here for Summer multiplayer: how the authority, clients, Worlds and Sessions fit, and which skill comes next."
|
|
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 summer_get_scene_tree summer_get_script_errors summer_project_setting
|
|
9
|
+
paths: ["**/*.gd", "**/*.tscn", "project.godot", "summer.build.json", "world.json"]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# /multiplayer — how Summer multiplayer works
|
|
13
|
+
|
|
14
|
+
Read this first, whatever the user asked for: "multiplayer", "co-op", "PvP",
|
|
15
|
+
"online", "play with friends", "lobby", "peer-to-peer", "host a game",
|
|
16
|
+
"netcode", "sync players". It explains the model in one page and sends you to
|
|
17
|
+
the skill that builds the next piece.
|
|
18
|
+
|
|
19
|
+
## The picture
|
|
20
|
+
|
|
21
|
+
A Summer multiplayer game is **one project with two entry scenes**:
|
|
22
|
+
|
|
23
|
+
- the **client** scene, which every player runs: input, camera, visuals, UI;
|
|
24
|
+
- the **authority** scene, which runs headless as the match server and owns
|
|
25
|
+
the rules.
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
each player's device Summer hosting (or Local Play)
|
|
29
|
+
┌──────────────────────┐ my pose ┌──────────────────────────────┐
|
|
30
|
+
│ client scene │ ─────────────► │ authority scene = one World │
|
|
31
|
+
│ moves its own player │ "collect" │ checks every pose and request│
|
|
32
|
+
│ draws everyone else │ ─────────────► │ owns score, doors, items... │
|
|
33
|
+
│ │ ◄───────────── │ │
|
|
34
|
+
└──────────────────────┘ state, events └──────────────────────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- A running match is a **World**. Summer starts one authority for it; the game
|
|
38
|
+
declares what a World is in `world.json` (a **WorldDefinition**).
|
|
39
|
+
- A player joins with `Summer.client.join(...)` and gets a verified
|
|
40
|
+
**Session**: their seat in that World, with a verified player identity.
|
|
41
|
+
- Players find a World through a **queue** in `summer.build.json`. Hosted,
|
|
42
|
+
Summer's matchmaking fills it; locally, **Local Play** starts the authority
|
|
43
|
+
and N clients on your machine.
|
|
44
|
+
- The same code runs locally and hosted. No `if server`, no local-only
|
|
45
|
+
branches, no IP addresses.
|
|
46
|
+
|
|
47
|
+
There is no player-hosted server, so there is no host migration, and a player
|
|
48
|
+
quitting never ends the match for the others.
|
|
49
|
+
|
|
50
|
+
## How data moves
|
|
51
|
+
|
|
52
|
+
Both sides load one **network composition** (`network/composition.tres`). It
|
|
53
|
+
declares every stream the game uses, and a **Spawner** node attaches it to the
|
|
54
|
+
World:
|
|
55
|
+
|
|
56
|
+
| You want | Use | Who writes it | Skill |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| My character moves | Owner-written State group, one per player | that player's client; the authority checks each pose | `multiplayer-movement` |
|
|
59
|
+
| Everyone sees the score, a door, the round timer | Authority-written State group, World audience | the authority | `multiplayer-state` |
|
|
60
|
+
| Only I see my wallet, hand, inventory | Authority-written State group, target-Session audience | the authority | `multiplayer-state` |
|
|
61
|
+
| A player wants to buy, open, collect, ready up | Command | client asks, authority accepts or refuses | `multiplayer-state` |
|
|
62
|
+
| A one-off effect (sparkle, sound, hit flash) | Event | the authority | `multiplayer-state` |
|
|
63
|
+
|
|
64
|
+
State is retained, so a late joiner gets the current value. Commands carry
|
|
65
|
+
the sender's verified Session. Events are fire-and-forget.
|
|
66
|
+
|
|
67
|
+
## The rules
|
|
68
|
+
|
|
69
|
+
1. **Each client moves its own character.** Movement feels instant on every
|
|
70
|
+
connection. The authority accepts or refuses each pose, and a refused pose
|
|
71
|
+
snaps the player back.
|
|
72
|
+
2. **The authority owns every other fact.** Clients never change shared
|
|
73
|
+
state; they send a Command and show the result.
|
|
74
|
+
3. **Identity comes from the Session**, never from a field a client sent.
|
|
75
|
+
4. **Never use the stock high-level multiplayer API in a Summer game:** no
|
|
76
|
+
`@rpc`, `MultiplayerSynchronizer`, `MultiplayerSpawner`,
|
|
77
|
+
`ENetMultiplayerPeer`, `multiplayer.is_server()` or peer-ID branches. Their
|
|
78
|
+
sender ids are transport peers, not verified players. Late joiners miss
|
|
79
|
+
state, and the game cannot use Summer hosting, matchmaking or identity.
|
|
80
|
+
5. **Test under a bad network before calling anything done:** Local Play
|
|
81
|
+
with latency, jitter and loss (`multiplayer-testing`).
|
|
82
|
+
|
|
83
|
+
## Words
|
|
84
|
+
|
|
85
|
+
| Word | Meaning |
|
|
86
|
+
|---|---|
|
|
87
|
+
| Game | Your game on Summer; its id is `gameId` in `summer.build.json` and the argument to `Summer.initialize` |
|
|
88
|
+
| World | One running match or shared place, simulated by one authority |
|
|
89
|
+
| WorldDefinition | `world.json`: which scenes run the client and the authority, lifetime, persistence |
|
|
90
|
+
| Queue | How players find a World; declared in `summer.build.json` |
|
|
91
|
+
| Session | One player's verified seat in a World |
|
|
92
|
+
| Composition | The network contract both sides load: State streams, Command and Event streams |
|
|
93
|
+
| State group | One retained value (a pose, a scoreboard); one writer, an audience |
|
|
94
|
+
| Command | A request from a client, answered by the authority |
|
|
95
|
+
| Event | A one-off message from the authority |
|
|
96
|
+
| Local Play | Runs the authority and N clients locally, with optional network emulation |
|
|
97
|
+
|
|
98
|
+
## Build it in this order
|
|
99
|
+
|
|
100
|
+
Each skill continues the same small game, so their code fits together:
|
|
101
|
+
|
|
102
|
+
1. **`multiplayer-project`**: the files, both entry scenes, joining, and a
|
|
103
|
+
first Local Play run.
|
|
104
|
+
2. **`multiplayer-movement`**: each player moves their own character; others
|
|
105
|
+
see it smoothly; the authority checks every pose.
|
|
106
|
+
3. **`multiplayer-state`**: score, doors, private inventories, Commands and
|
|
107
|
+
Events.
|
|
108
|
+
4. **`multiplayer-testing`**: Local Play under latency and loss, bots, and
|
|
109
|
+
what a passing run must show.
|
|
110
|
+
5. **`multiplayer-publish`**: export the summer.games bundle and upload it as
|
|
111
|
+
a Build.
|
|
112
|
+
|
|
113
|
+
## Add Summer services
|
|
114
|
+
|
|
115
|
+
| Skill | What it adds | Works in Local Play? |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| `summer-matchmaking` | Queues, match sizes, teams, the accept prompt, join failures | Yes, without the accept prompt |
|
|
118
|
+
| `summer-match-results` | Ending a match: winners, losers, rating changes | Yes |
|
|
119
|
+
| `summer-leaderboards` | Ratings and Game-wide leaderboards | Partly; reading boards needs hosting |
|
|
120
|
+
| `summer-parties` | Friends queue together as a party | No, hosted only |
|
|
121
|
+
| `summer-friends` | The player's Summer friends and direct messages | No, hosted only |
|
|
122
|
+
| `summer-player-data` | Progress that follows the player to any World | Yes, stored on disk |
|
|
123
|
+
| `summer-world-saves` | Worlds that persist between sessions | Yes, in memory |
|
|
124
|
+
| `summer-world-chat` | Text chat inside a World | No, hosted only |
|
|
125
|
+
| `summer-store` | Selling items for Sparks, owned items | Items yes; the store is hosted only |
|
|
126
|
+
| `summer-analytics` | Game events for your analytics dashboard | No, hosted only |
|
|
127
|
+
|
|
128
|
+
## What people ask for, and what Summer does
|
|
129
|
+
|
|
130
|
+
| They ask for | On Summer |
|
|
131
|
+
|---|---|
|
|
132
|
+
| "One player hosts", peer-to-peer | A headless authority per match, started by Summer or by Local Play |
|
|
133
|
+
| Host migration | Not needed: no player is the authority |
|
|
134
|
+
| Join by IP, invite code, server browser | Not available. Players join a queue; friends join as a party (`summer-parties`) |
|
|
135
|
+
| A lobby | A queue with `minPlayers`/`maxPlayers` and an accept prompt (`summer-matchmaking`) |
|
|
136
|
+
| "Sync the player's position" | An owner-written pose group (`multiplayer-movement`) |
|
|
137
|
+
| "Tell everyone the door opened" | An authority-written State group (`multiplayer-state`) |
|
|
138
|
+
| "The client asks the host to buy something" | A Command validated with the verified Session (`multiplayer-state`) |
|
|
139
|
+
| Save progress | Player data for the player, World saves for the place (`summer-player-data`, `summer-world-saves`) |
|
|
140
|
+
|
|
141
|
+
## Start
|
|
142
|
+
|
|
143
|
+
Check what exists: `summer.build.json`, `world.json`, `network/`,
|
|
144
|
+
`authority/`, `client/`.
|
|
145
|
+
|
|
146
|
+
- **None of them:** start with `multiplayer-project`.
|
|
147
|
+
- **They exist:** pick the skill for the piece you need from the tables above.
|
|
148
|
+
- **The game already uses `@rpc` or `MultiplayerSynchronizer`:** tell the user
|
|
149
|
+
it needs moving to Summer's networking. Then follow `multiplayer-project`
|
|
150
|
+
and port one system at a time: movement first, then state.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
id: skill/multiplayer
|
|
2
|
+
kind: skill
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
summary: "Start here for Summer multiplayer: how the authority, clients, Worlds and Sessions fit, and which skill comes next."
|
|
5
|
+
use_when:
|
|
6
|
+
- "the user wants multiplayer, co-op, PvP, online play over the internet, or to play with friends in a Summer game"
|
|
7
|
+
- "the user asks for peer-to-peer, a player-hosted server, host migration, join-by-IP or a lobby"
|
|
8
|
+
- "deciding how a multiplayer Summer game is structured before writing networking code"
|
|
9
|
+
- "a multiplayer game was built with @rpc or MultiplayerSynchronizer and needs moving to Summer's networking"
|
|
10
|
+
facets:
|
|
11
|
+
lifecycle:
|
|
12
|
+
- build
|
|
13
|
+
domains:
|
|
14
|
+
- multiplayer
|
|
15
|
+
- project
|
|
16
|
+
modalities:
|
|
17
|
+
- scripts
|
|
18
|
+
- scenes
|
|
19
|
+
compatibility:
|
|
20
|
+
engine: ">=4.6"
|
|
21
|
+
related:
|
|
22
|
+
skills:
|
|
23
|
+
- skill/multiplayer-project
|
|
24
|
+
- skill/multiplayer-movement
|
|
25
|
+
- skill/multiplayer-state
|
|
26
|
+
- skill/multiplayer-testing
|
|
27
|
+
- skill/multiplayer-publish
|
|
28
|
+
- skill/summer-matchmaking
|
|
29
|
+
- skill/summer-player-data
|
|
30
|
+
source: official
|
|
31
|
+
license: MIT
|
|
32
|
+
status: stable
|
|
33
|
+
recommended: true
|