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
|
@@ -270,9 +270,9 @@
|
|
|
270
270
|
{
|
|
271
271
|
"id": "template/3d-lan-multiplayer-starter",
|
|
272
272
|
"slug": "3d-lan-multiplayer-starter",
|
|
273
|
-
"version": "1.0.
|
|
273
|
+
"version": "1.0.2",
|
|
274
274
|
"summary": "3D LAN multiplayer starter built on GDQuest's open-source work — host/join flow and synced players.",
|
|
275
|
-
"status": "
|
|
275
|
+
"status": "deprecated",
|
|
276
276
|
"aliases": [
|
|
277
277
|
"template-3d-lan-multiplayer-starter"
|
|
278
278
|
],
|
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: host-authoritative-state
|
|
3
|
-
description: "Use when designing the state layer of a multiplayer Summer game: deciding what the host owns, how clients request changes, and how the host validates and broadcasts. Pairs with `/peer-to-peer-multiplayer`. Trigger on \"host authority\", \"authoritative state\", \"state ownership\", \"MP cheating\", \"client validation\", \"RPC patterns\"."
|
|
4
|
-
license: MIT
|
|
5
|
-
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
|
-
category: multiplayer-and-networking
|
|
7
|
-
user-invocable: true
|
|
8
|
-
allowed-tools: Read Grep summer_get_scene_tree summer_inspect_node summer_save_scene summer_get_script_errors
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# /host-authoritative-state — Designing the State Layer
|
|
12
|
-
|
|
13
|
-
## Overview
|
|
14
|
-
|
|
15
|
-
This is **Layer 2** of multiplayer architecture. `/peer-to-peer-multiplayer` covers all four layers; this skill zooms in on the one that produces 90% of shipping-quality MP bugs. For every piece of state in your game, decide: **does the host own it, or does the client own it?** Get this wrong and you ship a cheat-vulnerable, desync-prone game where players "teleport," items dupe, and hit-detection lies. Get it right and the rest of multiplayer falls into place.
|
|
16
|
-
|
|
17
|
-
## The fundamental question
|
|
18
|
-
|
|
19
|
-
For every state field, ask one question:
|
|
20
|
-
|
|
21
|
-
> **If a malicious client lies about this, does it break the game?**
|
|
22
|
-
|
|
23
|
-
| Answer | Owner | Notes |
|
|
24
|
-
|---|---|---|
|
|
25
|
-
| Yes | **Host-authoritative.** | Clients send intent (RPC request); host validates and broadcasts. |
|
|
26
|
-
| No | **Client-owned.** | Cosmetic. Replicated for visual sync only. |
|
|
27
|
-
| Sometimes | **Host-authoritative with client prediction.** | Position is the canonical example: client predicts to feel responsive; host reconciles to prevent teleport-cheats. |
|
|
28
|
-
|
|
29
|
-
This question is the entire decision tree. Apply it to every field, no exceptions.
|
|
30
|
-
|
|
31
|
-
## The decision matrix
|
|
32
|
-
|
|
33
|
-
The canonical state-ownership table for a typical 3D action game. Use this as your starting point and extend per game.
|
|
34
|
-
|
|
35
|
-
| State field | Owner | Why | What an attacker could do if you got it wrong |
|
|
36
|
-
|---|---|---|---|
|
|
37
|
-
| `health` | host | core combat integrity | edit memory → infinite HP, ignore damage |
|
|
38
|
-
| `mana` / `stamina` | host | gates ability/sprint use | infinite-cast spam, infinite-sprint |
|
|
39
|
-
| `score` / `kills` / `objectives` | host | competitive integrity | self-award kills, fake leaderboard |
|
|
40
|
-
| `inventory` contents | host | items must not dupe | broadcast "I picked it up" twice → duped item |
|
|
41
|
-
| `currency` (gold, gems) | host | trade exploits | mint currency on the client |
|
|
42
|
-
| `ability_cooldowns` | host | gates damage rate | spam-cast every frame |
|
|
43
|
-
| `current_weapon` equipped | host | tied to inventory and damage tables | swap to "best gun" without owning it |
|
|
44
|
-
| `team_assignment` | host | balance + friendly fire | switch sides mid-match |
|
|
45
|
-
| `ready_state` (lobby) | host | match-start gating | force-start with one player |
|
|
46
|
-
| `chat_messages` | host-relayed | moderation hooks, profanity filter | bypass mute, broadcast to muted peers |
|
|
47
|
-
| `position` | client-predicted, host-reconciled | input latency feels awful otherwise | speed-hack, teleport — reconciliation catches both |
|
|
48
|
-
| `velocity` | client-predicted, host-reconciled | same as position | same as position |
|
|
49
|
-
| `look_direction` (yaw/pitch) | **client** | cosmetic; host doesn't need it for hit-reg if you raycast on host | cheating here doesn't help |
|
|
50
|
-
| `animation_state` | **client** | visual; can lead the truth | wrong anim = visual glitch, not exploit |
|
|
51
|
-
| `footstep_audio` | **client** | host doesn't care | spam → mild annoyance, not exploit |
|
|
52
|
-
| `particle_fx` / `muzzle_flash` | **client** | host doesn't care | same |
|
|
53
|
-
| `aim_assist_target` | **client** | local UX | spoofing it only hurts the spoofer |
|
|
54
|
-
|
|
55
|
-
If a row is missing, run the fundamental question on it. When in doubt, host-own it — false positives are cheap, false negatives ship cheats.
|
|
56
|
-
|
|
57
|
-
## The Manager pattern
|
|
58
|
-
|
|
59
|
-
Every host-authoritative state field lives in a Manager autoload. Naming convention: `{Domain}Manager` — `HealthManager`, `ScoreManager`, `InventoryManager`, `CooldownManager`. This is the canonical state-ownership pattern across shipping-quality MP architectures.
|
|
60
|
-
|
|
61
|
-
Each Manager has a fixed shape:
|
|
62
|
-
|
|
63
|
-
```gdscript
|
|
64
|
-
class_name HealthManager
|
|
65
|
-
extends Node
|
|
66
|
-
|
|
67
|
-
# ── Signals (UI / floating bars / scoreboard listen here) ──
|
|
68
|
-
signal player_health_updated(peer_id: int, hp: int, max_hp: int)
|
|
69
|
-
signal player_died(peer_id: int, killer_id: int)
|
|
70
|
-
|
|
71
|
-
const DEFAULT_MAX_HEALTH := 100
|
|
72
|
-
|
|
73
|
-
# Host-authoritative dictionary, keyed by peer_id.
|
|
74
|
-
var _player_health: Dictionary = {} # peer_id -> { hp, max_hp, is_dead }
|
|
75
|
-
|
|
76
|
-
func _ready() -> void:
|
|
77
|
-
NetworkManager.peer_joined.connect(_on_peer_joined)
|
|
78
|
-
NetworkManager.peer_left.connect(_on_peer_left)
|
|
79
|
-
|
|
80
|
-
# ── HOST-ONLY MUTATORS (state writes) ──────────────────────────
|
|
81
|
-
func _host_apply_damage(target: int, amount: int, attacker: int) -> void:
|
|
82
|
-
if not NetworkManager.is_host: return
|
|
83
|
-
var entry = _player_health.get(target)
|
|
84
|
-
if entry == null or entry.is_dead: return
|
|
85
|
-
var new_hp = max(0, entry.hp - amount)
|
|
86
|
-
entry.hp = new_hp
|
|
87
|
-
_broadcast_health(target, new_hp, entry.max_hp)
|
|
88
|
-
if new_hp == 0:
|
|
89
|
-
entry.is_dead = true
|
|
90
|
-
_broadcast_death(target, attacker)
|
|
91
|
-
|
|
92
|
-
# ── CLIENT REQUEST HANDLERS (validate then mutate) ─────────────
|
|
93
|
-
@rpc("any_peer", "call_remote", "reliable")
|
|
94
|
-
func _client_request_damage(target: int, amount: int) -> void:
|
|
95
|
-
if not NetworkManager.is_host: return
|
|
96
|
-
var sender := multiplayer.get_remote_sender_id()
|
|
97
|
-
if not _validate_damage_request(sender, target, amount): return
|
|
98
|
-
_host_apply_damage(target, amount, sender)
|
|
99
|
-
|
|
100
|
-
# ── HOST-TO-CLIENT BROADCASTS (state reads) ────────────────────
|
|
101
|
-
@rpc("authority", "call_remote", "reliable")
|
|
102
|
-
func _broadcast_health(peer_id: int, hp: int, max_hp: int) -> void:
|
|
103
|
-
var entry = _player_health.get(peer_id, { "hp": hp, "max_hp": max_hp, "is_dead": false })
|
|
104
|
-
entry.hp = hp
|
|
105
|
-
entry.max_hp = max_hp
|
|
106
|
-
_player_health[peer_id] = entry
|
|
107
|
-
player_health_updated.emit(peer_id, hp, max_hp)
|
|
108
|
-
|
|
109
|
-
@rpc("authority", "call_remote", "reliable")
|
|
110
|
-
func _broadcast_death(peer_id: int, killer_id: int) -> void:
|
|
111
|
-
player_died.emit(peer_id, killer_id)
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
The shape:
|
|
115
|
-
|
|
116
|
-
1. **Data** lives in a private `Dictionary` keyed by `peer_id`.
|
|
117
|
-
2. **`_host_apply_*()` mutators** are the *only* functions that write the dictionary. First line: `if not NetworkManager.is_host: return`.
|
|
118
|
-
3. **`_client_request_*()` RPC handlers** validate, then call the mutator. Never write directly.
|
|
119
|
-
4. **`_broadcast_*()` RPC functions** push state to clients (`@rpc("authority", ...)`) so only host can call.
|
|
120
|
-
5. **Lifecycle** via `NetworkManager.peer_joined` / `peer_left` — host registers and cleans up entries.
|
|
121
|
-
|
|
122
|
-
Build one Manager per state domain. Don't put health and inventory in the same autoload — when one needs a refactor the other gets dragged along.
|
|
123
|
-
|
|
124
|
-
## The four RPC flavors
|
|
125
|
-
|
|
126
|
-
`/peer-to-peer-multiplayer` covers three; this skill goes deeper on a fourth (query/response). Every networked function maps to one of these. Pick the wrong one and you'll see the bug listed.
|
|
127
|
-
|
|
128
|
-
### Flavor 1: Host → Client broadcast
|
|
129
|
-
|
|
130
|
-
```gdscript
|
|
131
|
-
@rpc("authority", "call_remote", "reliable")
|
|
132
|
-
func _broadcast_score(peer: int, value: int) -> void:
|
|
133
|
-
_scores[peer] = value
|
|
134
|
-
score_updated.emit(peer, value)
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
- `authority` = only the host can call this. Summer Engine drops other calls.
|
|
138
|
-
- `call_remote` = doesn't run on the caller. Host already wrote the dictionary; no need to re-run locally.
|
|
139
|
-
- `reliable` = state must arrive. Lost packets retry.
|
|
140
|
-
- **Bug if wrong:** if you mark this `any_peer`, a client can fake a score broadcast → desync.
|
|
141
|
-
|
|
142
|
-
### Flavor 2: Client → Host request
|
|
143
|
-
|
|
144
|
-
```gdscript
|
|
145
|
-
@rpc("any_peer", "call_remote", "reliable")
|
|
146
|
-
func _client_request_use_item(item_id: String) -> void:
|
|
147
|
-
if not NetworkManager.is_host: return
|
|
148
|
-
var sender := multiplayer.get_remote_sender_id()
|
|
149
|
-
if not _validate_item_use(sender, item_id): return
|
|
150
|
-
_host_apply_item_use(sender, item_id)
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
- `any_peer` = any client can call.
|
|
154
|
-
- First line is **always** `if not NetworkManager.is_host: return`. Summer
|
|
155
|
-
Engine already routes correctly; this also guards against misconfiguration.
|
|
156
|
-
- `multiplayer.get_remote_sender_id()` is trustworthy — clients can't lie about who sent the request.
|
|
157
|
-
- **Bug if wrong:** missing the `is_host` guard means peers process each other's requests and corrupt local state.
|
|
158
|
-
|
|
159
|
-
### Flavor 3: Client → Client cosmetic relay
|
|
160
|
-
|
|
161
|
-
```gdscript
|
|
162
|
-
@rpc("any_peer", "call_remote", "unreliable")
|
|
163
|
-
func _peer_play_emote(emote_id: String) -> void:
|
|
164
|
-
var sender := multiplayer.get_remote_sender_id()
|
|
165
|
-
_play_emote_visual(sender, emote_id)
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
- `unreliable` = fire-and-forget, lossy is fine for cosmetics.
|
|
169
|
-
- No validation — worst case a player's emote desyncs by a frame.
|
|
170
|
-
- **Bug if wrong:** marking this `reliable` for high-frequency cosmetic events (footsteps, particle spawns) blows up bandwidth.
|
|
171
|
-
|
|
172
|
-
### Flavor 4: Query / response (the late-join flavor)
|
|
173
|
-
|
|
174
|
-
The flavor not covered in `/peer-to-peer-multiplayer`. When one specific client needs the host to send them state — e.g. a peer just joined and needs the full game state — use `rpc_id` to target a single peer.
|
|
175
|
-
|
|
176
|
-
```gdscript
|
|
177
|
-
# Client side — peer asks the host for current state
|
|
178
|
-
func client_request_full_state() -> void:
|
|
179
|
-
rpc_id(1, "_host_send_full_state_to_caller")
|
|
180
|
-
|
|
181
|
-
@rpc("any_peer", "call_remote", "reliable")
|
|
182
|
-
func _host_send_full_state_to_caller() -> void:
|
|
183
|
-
if not NetworkManager.is_host: return
|
|
184
|
-
var caller := multiplayer.get_remote_sender_id()
|
|
185
|
-
# send state ONLY to the caller, not all peers
|
|
186
|
-
for peer_id in _player_health:
|
|
187
|
-
var entry = _player_health[peer_id]
|
|
188
|
-
rpc_id(caller, "_broadcast_health", peer_id, entry.hp, entry.max_hp)
|
|
189
|
-
|
|
190
|
-
# Host side — actually a flavor 1 broadcast, but targeted via rpc_id
|
|
191
|
-
@rpc("authority", "call_remote", "reliable")
|
|
192
|
-
func _broadcast_health(peer_id: int, hp: int, max_hp: int) -> void:
|
|
193
|
-
# same handler as flavor 1, but called via rpc_id(caller, ...) for targeting
|
|
194
|
-
pass
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
Use this for: late-join state replay, lobby info on connect, post-respawn loadout. **Always reliable** — partial state replay is worse than no replay.
|
|
198
|
-
|
|
199
|
-
## Validation patterns
|
|
200
|
-
|
|
201
|
-
Every `_client_request_*()` must validate **before** applying. The validation is the only thing standing between you and a cheat.
|
|
202
|
-
|
|
203
|
-
```gdscript
|
|
204
|
-
func _validate_damage_request(attacker: int, target: int, amount: int) -> bool:
|
|
205
|
-
# 1. Authority check — does this client own the attacker?
|
|
206
|
-
if attacker != target_attacker_owner(attacker): return false
|
|
207
|
-
|
|
208
|
-
# 2. Existence check
|
|
209
|
-
if not _player_health.has(target): return false
|
|
210
|
-
if _player_health[target].is_dead: return false
|
|
211
|
-
|
|
212
|
-
# 3. Resource check — does attacker have a weapon equipped?
|
|
213
|
-
if not InventoryManager.has_weapon_equipped(attacker): return false
|
|
214
|
-
|
|
215
|
-
# 4. Range check — within weapon's max range?
|
|
216
|
-
var weapon := InventoryManager.get_equipped_weapon(attacker)
|
|
217
|
-
var dist := _get_player_distance(attacker, target)
|
|
218
|
-
if dist > weapon.max_range + 0.5: # epsilon for float compare
|
|
219
|
-
return false
|
|
220
|
-
|
|
221
|
-
# 5. Line-of-sight check — physics raycast on the host
|
|
222
|
-
if not _has_line_of_sight(attacker, target): return false
|
|
223
|
-
|
|
224
|
-
# 6. Cooldown check — is the weapon off cooldown?
|
|
225
|
-
if not CooldownManager.is_ready(attacker, weapon.id): return false
|
|
226
|
-
|
|
227
|
-
# 7. Damage cap — clamp `amount` to weapon.max_damage to defeat magnitude inflation
|
|
228
|
-
if amount > weapon.max_damage: return false
|
|
229
|
-
|
|
230
|
-
return true
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
Six common validators, in priority order:
|
|
234
|
-
|
|
235
|
-
1. **Authority** — does this client own the entity they're modifying? (You can attack other players, but you can only modify your *own* inventory.)
|
|
236
|
-
2. **Existence** — does the target still exist on the host? (Race vs. peer disconnect.)
|
|
237
|
-
3. **Resource** — does the requester have the resources? (Mana, ammo, weapon.)
|
|
238
|
-
4. **Range / distance** — physics-plausible? (Prevents shooting across the map.)
|
|
239
|
-
5. **Line-of-sight** — raycast on the host. (Prevents shooting through walls.)
|
|
240
|
-
6. **Cooldown** — within rate limits? (Prevents spam-cast.)
|
|
241
|
-
7. **Magnitude** — is the requested amount within game-defined max? (Prevents inflation: clamp damage to weapon's `max_damage`, etc.)
|
|
242
|
-
|
|
243
|
-
When validation fails: **drop silently or log + drop**. Never tell the client they tried to cheat — that just lets them probe. No error response, no friendly "you can't do that" message. The request simply has no effect.
|
|
244
|
-
|
|
245
|
-
**Float epsilon:** range / distance / cooldown checks involve floats. Always allow a small epsilon (`+ 0.5` for distance, `> -0.05` for cooldown remaining). Strict equality on floats fails for legitimate clients due to physics jitter.
|
|
246
|
-
|
|
247
|
-
## Late-join state sync
|
|
248
|
-
|
|
249
|
-
When a peer joins mid-session, the host must replay current state to them. Without this, the new peer's HUD shows zeros and they think they have full HP.
|
|
250
|
-
|
|
251
|
-
The pattern: every Manager exposes a `_send_full_state(peer_id)` method. Connect it to `NetworkManager.peer_joined`.
|
|
252
|
-
|
|
253
|
-
```gdscript
|
|
254
|
-
# In each Manager
|
|
255
|
-
func _on_peer_joined(id: int) -> void:
|
|
256
|
-
if not NetworkManager.is_host: return
|
|
257
|
-
# Register the new peer
|
|
258
|
-
_player_health[id] = { "hp": DEFAULT_MAX_HEALTH, "max_hp": DEFAULT_MAX_HEALTH, "is_dead": false }
|
|
259
|
-
# Replay all existing state to them
|
|
260
|
-
_send_full_state(id)
|
|
261
|
-
|
|
262
|
-
func _send_full_state(target_peer: int) -> void:
|
|
263
|
-
for peer_id in _player_health:
|
|
264
|
-
var entry = _player_health[peer_id]
|
|
265
|
-
rpc_id(target_peer, "_broadcast_health", peer_id, entry.hp, entry.max_hp)
|
|
266
|
-
if entry.is_dead:
|
|
267
|
-
rpc_id(target_peer, "_broadcast_death", peer_id, 0)
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
Use flavor 4 (`rpc_id`) so only the joining peer gets the replay. Broadcasting to all peers re-confirms state they already have — wastes bandwidth and may trigger "received update" hooks on UIs.
|
|
271
|
-
|
|
272
|
-
**Idempotency:** `_send_full_state` may run a fraction of a second after `_broadcast_health` for the same peer. Make sure your Manager's broadcast handlers are idempotent — receiving the same state twice should be a no-op.
|
|
273
|
-
|
|
274
|
-
## Common mistakes
|
|
275
|
-
|
|
276
|
-
| Mistake | What goes wrong | Fix |
|
|
277
|
-
|---|---|---|
|
|
278
|
-
| Trusting client-supplied damage values | Client edits memory → 99999 damage one-shots everyone | Host computes damage from weapon resource; client supplies only `target` and `weapon_id`. |
|
|
279
|
-
| Validating *after* applying instead of before | Cheat already took effect for a frame; reverting causes visual rubber-banding | Validate first, then mutate. The mutator never runs if validation fails. |
|
|
280
|
-
| Broadcasting state changes via `signal.emit()` on host | Signals fire only on the emitter — clients never see the update | Use `@rpc("authority", ...)` broadcast functions. Signals are for *local* listeners (UI on the host). |
|
|
281
|
-
| Forgetting `peer_left` cleanup | Dictionaries grow forever as players cycle through; eventual memory leak + ghost entries | Every Manager listens to `NetworkManager.peer_left` and `erase()`s its entry. |
|
|
282
|
-
| Using `reliable` for high-frequency cosmetic state (footsteps, particles) | Bandwidth blowup; reliable retransmits on packet loss | `unreliable` for cosmetic; `reliable` only for state that *must* arrive. |
|
|
283
|
-
| Comparing floats without epsilon in validation | Legitimate clients fail validation due to physics-step jitter; their hits get silently dropped | `dist > max_range + 0.5`, never `dist > max_range`. |
|
|
284
|
-
| Writing to host dictionary from a non-host code path | One peer accidentally becomes "second host" → desyncs | First line of every mutator: `if not NetworkManager.is_host: return`. Treat as boilerplate. |
|
|
285
|
-
|
|
286
|
-
## Anti-pattern: the "synced var" temptation
|
|
287
|
-
|
|
288
|
-
Summer Engine ships a `MultiplayerSynchronizer` node that automatically
|
|
289
|
-
replicates a list of properties across the network. It is tempting because it
|
|
290
|
-
removes RPC boilerplate. **It is wrong for anything game-logic-relevant.**
|
|
291
|
-
|
|
292
|
-
`MultiplayerSynchronizer`:
|
|
293
|
-
- Has no validation hook. Writes go through unconditionally.
|
|
294
|
-
- Has no concept of "host owns this, client requests changes."
|
|
295
|
-
- Replicates whatever value the configured authority node sets — and the authority is per-node, not per-property.
|
|
296
|
-
- Provides no audit trail when a value changes (compared to a Manager method you can breakpoint).
|
|
297
|
-
|
|
298
|
-
It is the right tool for **cosmetic state only**:
|
|
299
|
-
- Animation node parameters (`AnimationTree` blend values).
|
|
300
|
-
- Look direction / camera yaw on remote peer's visuals.
|
|
301
|
-
- Particle emission state on a non-gameplay decoration.
|
|
302
|
-
|
|
303
|
-
Game-logic state — health, score, inventory, cooldowns, position-of-truth — goes through Managers with explicit validate-mutate-broadcast. The five extra lines of boilerplate per field are what keeps the game shippable.
|
|
304
|
-
|
|
305
|
-
## Putting it together
|
|
306
|
-
|
|
307
|
-
When you start a new MP game, the order is:
|
|
308
|
-
|
|
309
|
-
1. Build `NetworkManager` (covered by `/peer-to-peer-multiplayer` Layer 1).
|
|
310
|
-
2. List every piece of game state on a sheet.
|
|
311
|
-
3. Run "if a malicious client lies, does it break?" on each.
|
|
312
|
-
4. Group host-owned fields by domain → one Manager per domain.
|
|
313
|
-
5. For each Manager: data dict, `_host_apply_*()` mutators, `_client_request_*()` RPCs with validators, `_broadcast_*()` RPCs, `peer_joined` / `peer_left` lifecycle, `_send_full_state()` for late-join.
|
|
314
|
-
6. Cosmetic state goes through `MultiplayerSynchronizer` or a flavor-3 RPC.
|
|
315
|
-
7. Position/velocity get host-reconciled prediction (covered by `/peer-to-peer-multiplayer` Layer 4).
|
|
316
|
-
|
|
317
|
-
## Collaborative protocol
|
|
318
|
-
|
|
319
|
-
This skill writes new autoload files (one per Manager). Always ask before each:
|
|
320
|
-
|
|
321
|
-
> May I create `autoloads/HealthManager.gd` and register it as an autoload?
|
|
322
|
-
> May I add the validation function to HealthManager? Here's what I'll check: [list].
|
|
323
|
-
> May I wire HealthManager's `peer_joined` lifecycle?
|
|
324
|
-
|
|
325
|
-
Don't bulk-create five Managers in one shot. Walk one Manager end-to-end (data → mutators → requests → broadcasts → lifecycle) so the user can verify the shape, then repeat for the next domain.
|
|
326
|
-
|
|
327
|
-
After each Manager file lands, call `summer_get_script_errors` to confirm clean compile.
|
|
328
|
-
|
|
329
|
-
## See also
|
|
330
|
-
|
|
331
|
-
- [`peer-to-peer-multiplayer`](../peer-to-peer-multiplayer/SKILL.md) — the four-layer architecture overview. Read this first if you haven't.
|
|
332
|
-
- [`setup-multiplayer`](../setup-multiplayer/SKILL.md) — lighter intro that just gets a session running. Use that one if the user just wants two players to see each other.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
id: skill/host-authoritative-state
|
|
2
|
-
kind: skill
|
|
3
|
-
version: 1.0.3
|
|
4
|
-
summary: Design the state layer of a multiplayer game — what the host owns, how clients request changes, and how the host validates and broadcasts.
|
|
5
|
-
use_when:
|
|
6
|
-
- "designing the state layer of a multiplayer Summer game: host ownership, client change requests, host validation and broadcast"
|
|
7
|
-
- clients desync, cheat, or fight over one object and the state ownership model is undefined
|
|
8
|
-
facets:
|
|
9
|
-
lifecycle:
|
|
10
|
-
- build
|
|
11
|
-
domains:
|
|
12
|
-
- multiplayer
|
|
13
|
-
- game-design
|
|
14
|
-
modalities:
|
|
15
|
-
- scripts
|
|
16
|
-
- scenes
|
|
17
|
-
compatibility:
|
|
18
|
-
engine: ">=4.6"
|
|
19
|
-
related:
|
|
20
|
-
skills:
|
|
21
|
-
- skill/peer-to-peer-multiplayer
|
|
22
|
-
- skill/setup-multiplayer
|
|
23
|
-
source: official
|
|
24
|
-
license: MIT
|
|
25
|
-
status: stable
|
|
26
|
-
recommended: true
|
|
27
|
-
aliases:
|
|
28
|
-
- skills/multiplayer-and-networking/host-authoritative-state
|