summer-engine 1.3.2 → 1.4.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.
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env bash
2
+ # Summer Engine — Pre-commit doctor hook (OPT-IN)
3
+ #
4
+ # Event: PreToolUse (matcher: Bash, if: "Bash(git commit*)")
5
+ # Purpose: Run `summer doctor` before any git commit Claude is about to make.
6
+ # Block the commit on FAIL. Allow with warnings on WARN.
7
+ #
8
+ # Status: OPT-IN. Not registered in the Summer plugin manifest by default.
9
+ #
10
+ # To enable, add to ~/.claude/settings.json (or .claude/settings.json):
11
+ #
12
+ # {
13
+ # "hooks": {
14
+ # "PreToolUse": [
15
+ # {
16
+ # "matcher": "Bash",
17
+ # "hooks": [
18
+ # {
19
+ # "type": "command",
20
+ # "command": "${CLAUDE_PLUGIN_ROOT}/hooks/pre-commit-doctor.sh",
21
+ # "if": "Bash(git commit*)",
22
+ # "timeout": 15
23
+ # }
24
+ # ]
25
+ # }
26
+ # ]
27
+ # }
28
+ # }
29
+ #
30
+ # Then: chmod +x ${CLAUDE_PLUGIN_ROOT}/hooks/pre-commit-doctor.sh
31
+ #
32
+ # Input: JSON on stdin: { tool_name, tool_input: { command, ... }, ... }
33
+ # Output: On FAIL: stderr explanation, exit 2 (blocks commit).
34
+ # On WARN: stderr warnings, exit 0 (allows commit).
35
+ # On PASS or no `summer` CLI: silent, exit 0.
36
+ #
37
+ # Portability: bash 3.2+, POSIX-friendly. jq optional.
38
+
39
+ set +e
40
+
41
+ INPUT=$(cat)
42
+
43
+ # ---------- Parse the command ----------
44
+ COMMAND=""
45
+ if command -v jq >/dev/null 2>&1; then
46
+ COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
47
+ fi
48
+ if [ -z "$COMMAND" ]; then
49
+ COMMAND=$(printf '%s' "$INPUT" \
50
+ | grep -oE '"command"[[:space:]]*:[[:space:]]*"[^"]*"' \
51
+ | head -1 \
52
+ | sed 's/^"command"[[:space:]]*:[[:space:]]*"//;s/"$//')
53
+ fi
54
+
55
+ # ---------- Bail early if not a git commit ----------
56
+ if ! printf '%s' "$COMMAND" | grep -qE '^[[:space:]]*git[[:space:]]+commit'; then
57
+ exit 0
58
+ fi
59
+
60
+ # ---------- Bail if `summer` CLI missing ----------
61
+ if ! command -v summer >/dev/null 2>&1; then
62
+ # Don't block — user may have installed via plugin only.
63
+ exit 0
64
+ fi
65
+
66
+ # ---------- Run doctor ----------
67
+ DOCTOR_OUT=$(summer doctor --json 2>/dev/null)
68
+ if [ -z "$DOCTOR_OUT" ]; then
69
+ exit 0
70
+ fi
71
+
72
+ # ---------- Parse status ----------
73
+ HAS_FAIL=0
74
+ HAS_WARN=0
75
+ FAIL_MSGS=""
76
+ WARN_MSGS=""
77
+
78
+ if command -v jq >/dev/null 2>&1; then
79
+ FAIL_MSGS=$(printf '%s' "$DOCTOR_OUT" \
80
+ | jq -r '.checks[]? | select(.status == "FAIL") | " - " + (.name // "?") + ": " + (.message // "")' 2>/dev/null)
81
+ WARN_MSGS=$(printf '%s' "$DOCTOR_OUT" \
82
+ | jq -r '.checks[]? | select(.status == "WARN") | " - " + (.name // "?") + ": " + (.message // "")' 2>/dev/null)
83
+ [ -n "$FAIL_MSGS" ] && HAS_FAIL=1
84
+ [ -n "$WARN_MSGS" ] && HAS_WARN=1
85
+ else
86
+ # Fallback: substring sniffing
87
+ if printf '%s' "$DOCTOR_OUT" | grep -q '"status"[[:space:]]*:[[:space:]]*"FAIL"'; then
88
+ HAS_FAIL=1
89
+ FAIL_MSGS=$(printf '%s' "$DOCTOR_OUT" \
90
+ | grep -oE '"status"[[:space:]]*:[[:space:]]*"FAIL"[^}]*"message"[[:space:]]*:[[:space:]]*"[^"]*"' \
91
+ | sed -E 's/.*"message"[[:space:]]*:[[:space:]]*"([^"]*)"/ - \1/')
92
+ fi
93
+ if printf '%s' "$DOCTOR_OUT" | grep -q '"status"[[:space:]]*:[[:space:]]*"WARN"'; then
94
+ HAS_WARN=1
95
+ WARN_MSGS=$(printf '%s' "$DOCTOR_OUT" \
96
+ | grep -oE '"status"[[:space:]]*:[[:space:]]*"WARN"[^}]*"message"[[:space:]]*:[[:space:]]*"[^"]*"' \
97
+ | sed -E 's/.*"message"[[:space:]]*:[[:space:]]*"([^"]*)"/ - \1/')
98
+ fi
99
+ fi
100
+
101
+ # ---------- FAIL: block ----------
102
+ if [ "$HAS_FAIL" -eq 1 ]; then
103
+ {
104
+ echo "=== Summer doctor: FAIL — commit blocked ==="
105
+ echo "$FAIL_MSGS"
106
+ echo ""
107
+ echo "Fix the failures above, or run: summer doctor"
108
+ echo "To bypass once: disable the pre-commit-doctor hook in settings.json."
109
+ echo "============================================"
110
+ } >&2
111
+ exit 2
112
+ fi
113
+
114
+ # ---------- WARN: allow with notice ----------
115
+ if [ "$HAS_WARN" -eq 1 ]; then
116
+ {
117
+ echo "=== Summer doctor: WARN — commit allowed ==="
118
+ echo "$WARN_MSGS"
119
+ echo "============================================"
120
+ } >&2
121
+ fi
122
+
123
+ exit 0
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bash
2
+ # Cross-platform hook dispatcher.
3
+ # Usage: run-hook.cmd <hook-name>
4
+ # Reads stdin, forwards to <plugin-root>/hooks/<hook-name>.sh
5
+ # On Windows, Claude Code / Cursor / Codex invoke this via Git-Bash.
6
+
7
+ HOOK_NAME="$1"
8
+ shift || true
9
+
10
+ HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
+ HOOK_SCRIPT="$HOOK_DIR/$HOOK_NAME.sh"
12
+
13
+ if [ ! -f "$HOOK_SCRIPT" ]; then
14
+ # Missing hook = no-op (don't break the host).
15
+ exit 0
16
+ fi
17
+
18
+ if [ ! -x "$HOOK_SCRIPT" ]; then
19
+ # Not executable yet (likely fresh checkout). Fall back to bash invocation.
20
+ exec bash "$HOOK_SCRIPT" "$@"
21
+ fi
22
+
23
+ exec "$HOOK_SCRIPT" "$@"
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env bash
2
+ # Summer Engine — SessionStart hook
3
+ #
4
+ # Event: SessionStart (matcher: startup|clear|compact)
5
+ # Purpose: Orient Claude on every fresh Summer-enabled session.
6
+ # Detect Godot project + GameSoul + doctor health, surface a one-line
7
+ # Bob-style greeting as additional context.
8
+ #
9
+ # Input: JSON on stdin with { session_id, source, model, cwd, ... }
10
+ # Common Claude Code env vars: $CLAUDE_PROJECT_DIR, $CLAUDE_PLUGIN_ROOT
11
+ # Output: JSON on stdout with hookSpecificOutput.additionalContext
12
+ # (also emits Cursor / Copilot CLI variants based on host env vars)
13
+ # Exit: Always 0 — never block session start.
14
+ #
15
+ # Portability: bash 3.2+ (macOS default), POSIX-friendly, works on Git Bash.
16
+ # Uses `grep -E` not `grep -P`. Falls back gracefully when jq
17
+ # and `summer` are missing.
18
+
19
+ set +e # Hooks must never kill the session.
20
+
21
+ # ---------- Resolve project dir ----------
22
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
23
+
24
+ # ---------- Build the orientation lines (max 3) ----------
25
+ LINES=()
26
+
27
+ # Line 1: Summer ready + skill count
28
+ SKILL_COUNT=""
29
+ if command -v summer >/dev/null 2>&1; then
30
+ # `summer skills count` is best-effort; ignore failure
31
+ SKILL_COUNT=$(summer skills count 2>/dev/null | grep -oE '[0-9]+' | head -1)
32
+ fi
33
+ if [ -n "$SKILL_COUNT" ]; then
34
+ LINES+=("Summer ready. ${SKILL_COUNT} skills.")
35
+ else
36
+ LINES+=("Summer ready.")
37
+ fi
38
+
39
+ # Line 2: Godot project + GameSoul one-liner (only if project.godot exists)
40
+ if [ -f "${PROJECT_DIR}/project.godot" ]; then
41
+ PROJECT_NAME=$(grep -E '^config/name=' "${PROJECT_DIR}/project.godot" 2>/dev/null \
42
+ | head -1 | sed 's/^config\/name=//;s/^"//;s/"$//')
43
+ [ -z "$PROJECT_NAME" ] && PROJECT_NAME=$(basename "$PROJECT_DIR")
44
+
45
+ SOUL_FILE="${PROJECT_DIR}/.summer/GameSoul.md"
46
+ if [ -f "$SOUL_FILE" ]; then
47
+ # First non-empty, non-heading paragraph (one line)
48
+ SOUL_LINE=$(awk 'BEGIN{p=""} /^[^#[:space:]]/ && NF>0 {p=$0; exit} END{print p}' \
49
+ "$SOUL_FILE" 2>/dev/null | cut -c1-120)
50
+ if [ -n "$SOUL_LINE" ]; then
51
+ LINES+=("Godot project: ${PROJECT_NAME}. GameSoul: ${SOUL_LINE}")
52
+ else
53
+ LINES+=("Godot project: ${PROJECT_NAME}.")
54
+ fi
55
+ else
56
+ LINES+=("Godot project: ${PROJECT_NAME}.")
57
+ fi
58
+ fi
59
+
60
+ # Line 3: doctor FAIL one-liner (only on FAIL — silent on PASS/WARN)
61
+ if command -v summer >/dev/null 2>&1; then
62
+ DOCTOR_OUT=$(summer doctor --json 2>/dev/null)
63
+ if [ -n "$DOCTOR_OUT" ]; then
64
+ FAIL_REASON=""
65
+ if command -v jq >/dev/null 2>&1; then
66
+ FAIL_REASON=$(printf '%s' "$DOCTOR_OUT" \
67
+ | jq -r 'first(.checks[]? | select(.status == "FAIL") | .message) // empty' 2>/dev/null)
68
+ else
69
+ # Crude fallback: first "message" near a "FAIL"
70
+ FAIL_REASON=$(printf '%s' "$DOCTOR_OUT" \
71
+ | grep -oE '"status"[[:space:]]*:[[:space:]]*"FAIL"[^}]*"message"[[:space:]]*:[[:space:]]*"[^"]*"' \
72
+ | head -1 \
73
+ | grep -oE '"message"[[:space:]]*:[[:space:]]*"[^"]*"' \
74
+ | sed 's/.*"message"[[:space:]]*:[[:space:]]*"//;s/"$//')
75
+ fi
76
+ if [ -n "$FAIL_REASON" ]; then
77
+ LINES+=("Summer setup needs attention: ${FAIL_REASON}. Run: summer doctor")
78
+ fi
79
+ fi
80
+ fi
81
+
82
+ # ---------- Compose context ----------
83
+ CONTEXT=""
84
+ for line in "${LINES[@]}"; do
85
+ if [ -z "$CONTEXT" ]; then CONTEXT="$line"
86
+ else CONTEXT="${CONTEXT}"$'\n'"$line"
87
+ fi
88
+ done
89
+
90
+ # Bail with empty JSON if we somehow have no lines
91
+ if [ -z "$CONTEXT" ]; then
92
+ printf '{}\n'
93
+ exit 0
94
+ fi
95
+
96
+ # ---------- JSON-escape for embedding ----------
97
+ escape_for_json() {
98
+ local s="$1"
99
+ s="${s//\\/\\\\}"
100
+ s="${s//\"/\\\"}"
101
+ s="${s//$'\n'/\\n}"
102
+ s="${s//$'\r'/\\r}"
103
+ s="${s//$'\t'/\\t}"
104
+ printf '%s' "$s"
105
+ }
106
+ CONTEXT_ESC=$(escape_for_json "$CONTEXT")
107
+
108
+ # ---------- Emit per-host shape ----------
109
+ # Cursor: top-level additional_context (snake_case)
110
+ # Claude Code: nested hookSpecificOutput.additionalContext
111
+ # Copilot CLI / SDK standard: top-level additionalContext (camelCase)
112
+ if [ -n "${CURSOR_PLUGIN_ROOT:-}" ]; then
113
+ printf '{"additional_context":"%s"}\n' "$CONTEXT_ESC"
114
+ elif [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -z "${COPILOT_CLI:-}" ]; then
115
+ printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"}}\n' "$CONTEXT_ESC"
116
+ else
117
+ printf '{"additionalContext":"%s"}\n' "$CONTEXT_ESC"
118
+ fi
119
+
120
+ exit 0
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/claude-code-marketplace.json",
3
+ "name": "summer",
4
+ "description": "Summer Engine plugins for Claude Code",
5
+ "owner": { "name": "Summer Engine", "email": "founders@summerengine.com" },
6
+ "plugins": [
7
+ {
8
+ "name": "summer",
9
+ "source": "./",
10
+ "version": "1.4.0",
11
+ "description": "AI game-dev studio: 19 skills under summer: namespace, MCP bridge, session-start + pre-commit hooks.",
12
+ "author": { "name": "Summer Engine", "email": "founders@summerengine.com" },
13
+ "category": "game-development",
14
+ "tags": ["game-dev", "godot", "ai-game-engine"],
15
+ "keywords": ["game-dev", "godot", "ai-game-engine", "skills"],
16
+ "brandColor": "#FF8F17",
17
+ "capabilities": ["Interactive", "Read", "Write"],
18
+ "defaultPrompt": [
19
+ "I want to make a game.",
20
+ "/summer:brainstorm-game"
21
+ ]
22
+ }
23
+ ]
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "summer-engine",
3
- "version": "1.3.2",
3
+ "version": "1.4.0",
4
4
  "description": "CLI and MCP tools for Summer Engine — the AI-native game engine",
5
5
  "keywords": [
6
6
  "game-engine",
@@ -25,6 +25,14 @@
25
25
  "files": [
26
26
  "dist/",
27
27
  "skills/",
28
+ "hooks/",
29
+ ".claude-plugin/",
30
+ ".cursor-plugin/",
31
+ ".codex-plugin/",
32
+ ".opencode/",
33
+ "gemini-extension.json",
34
+ "marketplace.json",
35
+ ".mcp.json",
28
36
  "README.md",
29
37
  "LICENSE",
30
38
  "CHANGELOG.md"
@@ -0,0 +1,99 @@
1
+ # Skill Spec: /peer-to-peer-multiplayer
2
+
3
+ ## Fixture
4
+
5
+ - A Godot 4.5 / Summer Engine project that does NOT yet have multiplayer.
6
+ - Project may be empty or may have an existing single-player scene.
7
+ - Summer MCP tools available; engine running on localhost:6550.
8
+
9
+ ## Case 1: Happy Path — fresh multiplayer architecture from scratch
10
+
11
+ **Input:** "I want to add 2-player co-op to my game. Players will connect through Steam friend invites."
12
+
13
+ **Expected behavior:**
14
+
15
+ 1. Skill confirms P2P is the right architecture (Steam friend invite ≤8 players → P2P, not dedicated server).
16
+ 2. Skill walks the four layers in order, checkpointing between each.
17
+ 3. Layer 1: asks "May I create `autoloads/network_manager.gd`?" — creates it on user OK, calls `summer_project_setting` to register the autoload.
18
+ 4. Layer 2: asks "May I create `autoloads/game_state.gd` and walk through the authority decision matrix?" — creates it, prompts user for game-specific state fields and proposes ownership.
19
+ 5. Layer 3: explains the three RPC patterns with examples; doesn't auto-apply (this is reference material until concrete game logic exists).
20
+ 6. Layer 4: defers prediction/interpolation until there's a player scene to apply it to.
21
+
22
+ **Expected MCP tool sequence (in order, partial):**
23
+
24
+ 1. `summer_get_scene_tree` — see what already exists.
25
+ 2. `summer_get_project_context` — read autoload list to avoid name collisions.
26
+ 3. (User approves Layer 1) `Write autoloads/network_manager.gd`.
27
+ 4. `summer_project_setting(key="autoload/NetworkManager", value="*res://autoloads/network_manager.gd")`.
28
+ 5. (User approves Layer 2) `Write autoloads/game_state.gd`.
29
+ 6. `summer_project_setting(key="autoload/GameState", value="*res://autoloads/game_state.gd")`.
30
+ 7. `summer_save_scene` and `summer_get_script_errors` to verify clean.
31
+
32
+ **Assertions:**
33
+
34
+ - [ ] Skill explicitly checks Step 0 (P2P vs. client-server) before any code is written.
35
+ - [ ] Skill creates Layer 1 (NetworkManager) before Layer 2 (GameState).
36
+ - [ ] NetworkManager is the only place that calls `multiplayer.peer_connected.connect()` directly. GameState listens to NetworkManager signals, NOT to the multiplayer API directly.
37
+ - [ ] GameState uses `@rpc("authority", "call_remote", "reliable")` for host-broadcast functions and `@rpc("any_peer", "call_remote", "reliable")` with a `is_host` guard for client-request functions.
38
+ - [ ] Skill walks the user through the authority decision matrix before writing GameState. Doesn't dump generic state fields without asking what the game has.
39
+ - [ ] Skill asks "May I…" before each new file creation and before the autoload registration.
40
+ - [ ] Skill does NOT apply prediction/interpolation in Layer 4 unless there's an existing player scene to wire into.
41
+ - [ ] At any layer, `summer_get_script_errors` is called after the file write to confirm clean compile.
42
+
43
+ ## Case 2: Failure Path — user wants matchmaking at scale
44
+
45
+ **Input:** "I'm building a competitive shooter. I want matchmaking with anti-cheat for 10,000 concurrent matches."
46
+
47
+ **Expected behavior:**
48
+
49
+ - Skill recognizes Step 0: this is dedicated client-server territory, not P2P.
50
+ - Skill explains why P2P is wrong (host can cheat, no anti-cheat hooks, scale concerns).
51
+ - Skill defers to `/summer:client-server-multiplayer` (when shipped) OR explains the user needs to roll a custom server.
52
+ - Does NOT start writing P2P NetworkManager code anyway.
53
+
54
+ **Assertions:**
55
+
56
+ - [ ] Skill stops at Step 0 — does NOT proceed to Layer 1.
57
+ - [ ] Skill explains the architecture mismatch in one sentence.
58
+ - [ ] Skill names the right alternative (client-server) and which skill to use instead.
59
+
60
+ ## Case 3: Edge Case — retrofitting multiplayer to a single-player game
61
+
62
+ **Input:** "I have a single-player platformer that's mostly done. Can you add multiplayer?"
63
+
64
+ **Expected behavior:**
65
+
66
+ - Skill is honest about the cost: retrofitting multiplayer is 5× harder than starting MP-first.
67
+ - Skill asks: "Are you committed? It will require auditing every state mutation in your existing code. Time estimate: significant."
68
+ - If user proceeds: skill walks the same 4 layers but adds an AUDIT phase before Layer 2: identify every place existing code writes to state that should be host-authoritative.
69
+ - If user balks: skill points to alternatives (release MP as a sequel; ship single-player; add async leaderboards instead).
70
+
71
+ **Assertions:**
72
+
73
+ - [ ] Skill warns about retrofit cost BEFORE starting Layer 1.
74
+ - [ ] Skill adds an AUDIT step that doesn't exist in the happy-path workflow.
75
+ - [ ] Skill never silently proceeds as if the game were greenfield.
76
+
77
+ ## Case 4: No Summer MCP — fallback path
78
+
79
+ **Fixture:** Same as Case 1, but Summer MCP unavailable.
80
+
81
+ **Input:** "Add multiplayer to my Godot game (P2P, friend invite)."
82
+
83
+ **Expected behavior:**
84
+
85
+ - Skill detects MCP unavailable.
86
+ - Walks the same 4 layers.
87
+ - Instead of `summer_project_setting`, asks the user to manually edit `project.godot`'s `[autoload]` section — provides the exact lines to paste.
88
+ - Instead of `summer_save_scene` / `summer_get_script_errors`, asks the user to save and check errors via the Godot editor.
89
+ - All file writes still go through `Write` host tool with "May I…" approval per file.
90
+
91
+ **Assertions:**
92
+
93
+ - [ ] Skill detects MCP unavailable; doesn't blindly call `summer_*` tools and fail.
94
+ - [ ] Project.godot edits are provided as exact paste-able lines.
95
+ - [ ] Workflow shape (4 layers, checkpoints between) is identical regardless of MCP availability.
96
+
97
+ ---
98
+
99
+ This spec runs via `/skill-test peer-to-peer-multiplayer spec` (see `_meta/skill-test/SKILL.md`).
@@ -233,3 +233,11 @@ summer_generate_audio(capability="text_to_speech", text="You shall not pass!", v
233
233
  - **Extremely thin objects** (paper, cloth, flags): 3D gen produces thick meshes. Better to use MeshInstance3D with a plane + texture + shader.
234
234
  - **Emissive/glowing objects**: Generate the mesh, add emissive material in engine. Don't rely on the glow being in the mesh.
235
235
  - **LOD (Level of Detail)**: Generate one version. If perf needs LOD, use Godot's LOD system or generate a second low-poly version.
236
+
237
+ ## Fallback
238
+
239
+ No fallback for this — Summer MCP required for the generation pipelines (`summer_generate_image`, `summer_generate_3d`, `summer_generate_audio`, `summer_search_assets`, `summer_import_from_url`). If MCP isn't connected, the user must source assets externally (Sketchfab, Quaternius, Kenney, AmbientCG) and import via Godot's import system.
240
+
241
+ ## Collaborative protocol
242
+
243
+ This skill triggers metered generation (image / 3D / audio) and mutates the scene with imported assets. Always ask before generating ("May I generate a 3D treasure chest via image-to-3D? This is one metered generation.") and before importing ("May I import the result to `res://assets/models/chest.glb`?"). See `../../_shared/collaborative-protocol.md`.
@@ -48,6 +48,13 @@ skills:
48
48
  public: true
49
49
 
50
50
  # ── gameplay-mechanics ──
51
+ - name: design-mechanic
52
+ category: gameplay-mechanics
53
+ status: HAVE
54
+ public: true
55
+ recommended: true
56
+ user-invocable: true
57
+ last-tested: 2026-05-05
51
58
  - name: melee-combat
52
59
  category: gameplay-mechanics
53
60
  status: NEXT
@@ -132,6 +139,13 @@ skills:
132
139
  public: true
133
140
 
134
141
  # ── scene-and-project ──
142
+ - name: brainstorm-game
143
+ category: scene-and-project
144
+ status: HAVE
145
+ public: true
146
+ recommended: true
147
+ user-invocable: true
148
+ last-tested: 2026-05-05
135
149
  - name: scene-composition
136
150
  category: scene-and-project
137
151
  status: HAVE
@@ -177,6 +191,13 @@ skills:
177
191
  public: true
178
192
 
179
193
  # ── rendering-and-lighting ──
194
+ - name: art-direction
195
+ category: rendering-and-lighting
196
+ status: HAVE
197
+ public: true
198
+ recommended: true
199
+ user-invocable: true
200
+ last-tested: 2026-05-05
180
201
  - name: 3d-lighting
181
202
  category: rendering-and-lighting
182
203
  status: HAVE
@@ -255,6 +276,13 @@ skills:
255
276
  public: true
256
277
 
257
278
  # ── visual-effects ──
279
+ - name: vfx
280
+ category: visual-effects
281
+ status: HAVE
282
+ public: true
283
+ recommended: true
284
+ user-invocable: true
285
+ last-tested: 2026-05-05
258
286
  - name: gpuparticles-3d-basics
259
287
  category: visual-effects
260
288
  status: NEXT
@@ -333,6 +361,13 @@ skills:
333
361
  public: true
334
362
 
335
363
  # ── audio ──
364
+ - name: audio-direction
365
+ category: audio
366
+ status: HAVE
367
+ public: true
368
+ recommended: true
369
+ user-invocable: true
370
+ last-tested: 2026-05-05
336
371
  - name: audio-bus-setup
337
372
  category: audio
338
373
  status: NEXT
@@ -393,6 +428,25 @@ skills:
393
428
  public: true
394
429
 
395
430
  # ── multiplayer-and-networking ──
431
+ - name: setup-multiplayer
432
+ category: multiplayer-and-networking
433
+ status: HAVE
434
+ public: true
435
+ recommended: true
436
+ user-invocable: true
437
+ last-tested: 2026-05-05
438
+ - name: peer-to-peer-multiplayer
439
+ category: multiplayer-and-networking
440
+ status: NEXT
441
+ public: true
442
+ recommended: true
443
+ user-invocable: true
444
+ - name: host-authoritative-state
445
+ category: multiplayer-and-networking
446
+ status: NEXT
447
+ public: true
448
+ recommended: true
449
+ user-invocable: true
396
450
  - name: multiplayerapi-basics
397
451
  category: multiplayer-and-networking
398
452
  status: NEXT
@@ -423,6 +477,13 @@ skills:
423
477
  public: true
424
478
 
425
479
  # ── ai-and-npcs ──
480
+ - name: design-npc
481
+ category: ai-and-npcs
482
+ status: HAVE
483
+ public: true
484
+ recommended: true
485
+ user-invocable: true
486
+ last-tested: 2026-05-05
426
487
  - name: navmesh-pathfinding
427
488
  category: ai-and-npcs
428
489
  status: NEXT
@@ -453,6 +514,13 @@ skills:
453
514
  public: true
454
515
 
455
516
  # ── level-design ──
517
+ - name: design-level
518
+ category: level-design
519
+ status: HAVE
520
+ public: true
521
+ recommended: true
522
+ user-invocable: true
523
+ last-tested: 2026-05-05
456
524
  - name: gridmap-building
457
525
  category: level-design
458
526
  status: NEXT
@@ -479,6 +547,13 @@ skills:
479
547
  public: true
480
548
 
481
549
  # ── performance ──
550
+ - name: tune-performance
551
+ category: performance
552
+ status: HAVE
553
+ public: true
554
+ recommended: true
555
+ user-invocable: true
556
+ last-tested: 2026-05-05
482
557
  - name: profiling-godot
483
558
  category: performance
484
559
  status: NEXT
@@ -624,6 +699,13 @@ skills:
624
699
  public: true
625
700
 
626
701
  # ── deployment ──
702
+ - name: export-and-ship
703
+ category: deployment
704
+ status: HAVE
705
+ public: true
706
+ recommended: true
707
+ user-invocable: true
708
+ last-tested: 2026-05-05
627
709
  - name: export-presets
628
710
  category: deployment
629
711
  status: NEXT
@@ -131,3 +131,30 @@ For `summer_set_resource_property` on CapsuleShape3D:
131
131
  - **Falling through floor:** Ensure the floor has a StaticBody3D or similar with a CollisionShape3D
132
132
  - **Camera clipping:** If the camera goes inside geometry, enable `near` on the Camera3D or add collision exception
133
133
  - **Mouse capture:** For FPS, you typically need `Input.mouse_mode = Input.MOUSE_MODE_CAPTURED` in `_ready()` and a way to release (e.g., Escape)
134
+
135
+ ## Fallback (no MCP — edit `.tscn` directly)
136
+
137
+ If Summer MCP isn't connected, write the scene by hand. Save as `res://player.tscn`:
138
+
139
+ ```
140
+ [gd_scene load_steps=2 format=3]
141
+
142
+ [sub_resource type="CapsuleShape3D" id="1"]
143
+ radius = 0.4
144
+ height = 1.6
145
+
146
+ [node name="Player" type="CharacterBody3D"]
147
+ position = Vector3(0, 1, 0)
148
+
149
+ [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
150
+ shape = SubResource("1")
151
+
152
+ [node name="Camera3D" type="Camera3D" parent="."]
153
+ position = Vector3(0, 1.6, 0)
154
+ ```
155
+
156
+ Then attach `player.gd` (script body above) via the inspector.
157
+
158
+ ## Collaborative protocol
159
+
160
+ This skill writes scene nodes and a `.gd` script. Always ask before applying. Group writes per phase: "May I add the Player + CollisionShape3D + Camera3D, bind WASD/jump InputMap actions, and attach `player.gd`?" See `../../_shared/collaborative-protocol.md`.