summer-engine 1.3.2 → 1.5.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/plugin.json +59 -0
- package/.codex-plugin/plugin.json +38 -0
- package/.cursor-plugin/plugin.json +42 -0
- package/.mcp.json +8 -0
- package/.opencode/plugins/summer.js +49 -0
- package/README.md +13 -0
- package/dist/lib/skills-registry.d.ts +96 -0
- package/dist/lib/skills-registry.js +205 -0
- package/gemini-extension.json +21 -0
- package/hooks/hooks-cursor.json +21 -0
- package/hooks/hooks.json +31 -0
- package/hooks/pre-commit-doctor.sh +123 -0
- package/hooks/run-hook.cmd +23 -0
- package/hooks/session-start.sh +120 -0
- package/marketplace.json +24 -0
- package/package.json +9 -1
- package/skills/_tests/specs/design-npc.md +43 -12
- package/skills/_tests/specs/fps-controller.md +33 -20
- package/skills/_tests/specs/host-authoritative-state.md +104 -0
- package/skills/_tests/specs/peer-to-peer-multiplayer.md +99 -0
- package/skills/_tests/specs/vfx.md +56 -38
- package/skills/ai-and-npcs/design-npc/SKILL.md +264 -122
- package/skills/asset-pipeline/asset-strategy/SKILL.md +8 -0
- package/skills/catalog.yaml +84 -0
- package/skills/character-controllers/fps-controller/SKILL.md +277 -69
- package/skills/multiplayer-and-networking/host-authoritative-state/SKILL.md +332 -0
- package/skills/multiplayer-and-networking/peer-to-peer-multiplayer/SKILL.md +378 -0
- package/skills/rendering-and-lighting/3d-lighting/SKILL.md +20 -0
- package/skills/scene-and-project/make-game/SKILL.md +10 -0
- package/skills/scene-and-project/scene-composition/SKILL.md +8 -0
- package/skills/ui-and-ux/ui-basics/SKILL.md +28 -0
- package/skills/visual-effects/vfx/SKILL.md +233 -134
|
@@ -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`).
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## Fixture
|
|
4
4
|
|
|
5
|
-
- Godot 4.5 / Summer Engine project, main scene with `World/Player` (CharacterBody3D + Camera3D) and `World/Enemy` (CharacterBody3D + MeshInstance3D + a `damaged` signal
|
|
5
|
+
- Godot 4.5 / Summer Engine project, main scene with `World/Player` (CharacterBody3D + Camera3D) and `World/Enemy` (CharacterBody3D + MeshInstance3D + a `damaged(amount)` signal).
|
|
6
|
+
- `default_bus_layout.tres` defines `Master`, `Music`, `Ambient`, `SFX` buses (at minimum).
|
|
6
7
|
- Summer MCP tools available (engine running on localhost:6550).
|
|
7
8
|
- Host file tools available (Read, Edit, Write).
|
|
8
9
|
|
|
@@ -12,14 +13,16 @@
|
|
|
12
13
|
|
|
13
14
|
**Expected behavior:**
|
|
14
15
|
|
|
15
|
-
1. Skill asks one focused question: "What feels flat? combat hits /
|
|
16
|
+
1. Skill asks one focused question: "What feels flat? combat hits / pickups / explosions / spell casts / something else."
|
|
16
17
|
2. User says "combat hits".
|
|
17
|
-
3. Skill calls `summer_get_scene_tree`,
|
|
18
|
-
4. Skill proposes
|
|
18
|
+
3. Skill calls `summer_get_scene_tree`, `summer_inspect_node "./World/Enemy"`, `summer_inspect_node "./World/Player/Camera3D"`, and confirms the audio bus list.
|
|
19
|
+
4. Skill proposes the full trio bundle: "I'm about to add HitFlash on `./World/Enemy`, CameraShake script on `./World/Player/Camera3D`, AudioDucker autoload, and wire the `damaged` signal so one hit fires all three. OK?"
|
|
19
20
|
5. After user OK:
|
|
20
21
|
- `summer_add_node(parent="./World/Enemy", type="Node", name="HitFlash")`
|
|
21
|
-
- `Write scripts/hit_flash.gd`
|
|
22
|
-
- `Write scripts/camera_shake.gd`
|
|
22
|
+
- `Write scripts/vfx/hit_flash.gd`
|
|
23
|
+
- `Write scripts/vfx/camera_shake.gd`
|
|
24
|
+
- `Write scripts/vfx/audio_ducker.gd`
|
|
25
|
+
- Register `AudioDucker` as an autoload (project settings or `.cfg` edit).
|
|
23
26
|
- `summer_connect_signal(from="./World/Enemy", signal="damaged", to="./World/Enemy/HitFlash", method="flash")`
|
|
24
27
|
- `summer_save_scene`
|
|
25
28
|
- `summer_get_script_errors`
|
|
@@ -27,71 +30,86 @@
|
|
|
27
30
|
**Assertions:**
|
|
28
31
|
|
|
29
32
|
- [ ] Skill asks the "what feels flat?" question before any tool call.
|
|
30
|
-
- [ ] Skill reads
|
|
33
|
+
- [ ] Skill reads scene tree AND inspects both Enemy mesh and Player Camera3D before mutation.
|
|
34
|
+
- [ ] Skill confirms audio bus names exist before installing AudioDucker.
|
|
31
35
|
- [ ] Skill explicitly states the bundle of changes and asks "May I" / "OK?" before mutation.
|
|
32
|
-
- [ ] HitFlash
|
|
36
|
+
- [ ] HitFlash uses `create_tween()` + `tween_callback`, NOT `await create_timer().timeout`.
|
|
37
|
+
- [ ] HitFlash kills any in-flight tween on re-entry (rapid hits).
|
|
33
38
|
- [ ] CameraShake uses quadratic falloff (`_trauma * _trauma`), NOT linear.
|
|
34
|
-
- [ ]
|
|
39
|
+
- [ ] CameraShake subtracts last frame's `_shake_offset` before applying the new one.
|
|
40
|
+
- [ ] AudioDucker captures `_initial_volumes` once in `_ready()` and applies ducking as an offset (relative dB drop), NOT absolute writes.
|
|
41
|
+
- [ ] AudioDucker kills any in-flight tween before starting a new duck.
|
|
42
|
+
- [ ] Final hit flash duration is 0.06–0.12 sec.
|
|
43
|
+
- [ ] Skill never calls `summer_set_resource_property` on an inline sub_resource (e.g. for the flash StandardMaterial3D).
|
|
35
44
|
- [ ] Skill ends with `summer_save_scene` then `summer_get_script_errors`.
|
|
36
|
-
- [ ] Final hit flash duration is 0.06–0.12 sec (NOT 0.3 sec).
|
|
37
45
|
|
|
38
|
-
## Case 2: Failure Path —
|
|
46
|
+
## Case 2: Failure Path — missing audio buses
|
|
39
47
|
|
|
40
|
-
**Fixture:** `
|
|
48
|
+
**Fixture:** project's `default_bus_layout.tres` has only `Master`. No `Music`, `Ambient`, `SFX`.
|
|
41
49
|
|
|
42
|
-
**Input:** "Add
|
|
50
|
+
**Input:** "Add hit feedback. Audio ducking too."
|
|
43
51
|
|
|
44
52
|
**Expected behavior:**
|
|
45
53
|
|
|
46
|
-
- Skill calls `summer_get_scene_tree`
|
|
47
|
-
-
|
|
48
|
-
-
|
|
54
|
+
- Skill calls `summer_get_scene_tree` then inspects the bus layout (or asks the user to paste it).
|
|
55
|
+
- Sees only `Master` exists.
|
|
56
|
+
- Skill does NOT install AudioDucker silently — it explains: "Audio ducking only works if at least Music/Ambient/SFX buses exist. With one Master bus, ducking would also duck the impact SFX you're trying to highlight. I can either (a) install hit-flash + camera-shake now and defer ducking until you set up buses via the `audio-direction` skill, or (b) walk through bus setup first."
|
|
57
|
+
- Waits for user choice.
|
|
58
|
+
- Whichever path: hit-flash + camera-shake still install correctly.
|
|
49
59
|
|
|
50
60
|
**Assertions:**
|
|
51
61
|
|
|
52
|
-
- [ ] Skill detects
|
|
53
|
-
- [ ] Skill does NOT
|
|
54
|
-
- [ ] Skill names
|
|
62
|
+
- [ ] Skill detects single-bus layout and stops to ask.
|
|
63
|
+
- [ ] Skill does NOT register AudioDucker autoload silently.
|
|
64
|
+
- [ ] Skill names `audio-direction` skill as the prerequisite.
|
|
65
|
+
- [ ] Skill still ships the other two systems in this session if the user picks (a).
|
|
55
66
|
|
|
56
|
-
## Case 3: Edge Case —
|
|
67
|
+
## Case 3: Edge Case — pickup pulse without trauma
|
|
57
68
|
|
|
58
|
-
**Fixture:** Same as Case 1.
|
|
69
|
+
**Fixture:** Same as Case 1, but the user is polishing pickups (peaceful glow), not combat.
|
|
59
70
|
|
|
60
|
-
**Input:** "
|
|
71
|
+
**Input:** "Make my health pickups feel more rewarding when collected."
|
|
61
72
|
|
|
62
73
|
**Expected behavior:**
|
|
63
74
|
|
|
64
|
-
- Skill
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
75
|
+
- Skill asks the focused question; user says "pickups".
|
|
76
|
+
- Skill recognizes pickups should NOT trigger camera shake or aggressive audio ducking — those read as combat, not reward.
|
|
77
|
+
- Skill installs only the HitFlash module (renaming usage as a pickup pulse — same script, called on collection), and proposes a small upward duck (0.2 amount, 0.3 duration) so the pickup "ding" reads above ambient.
|
|
78
|
+
- Skill explicitly says: "Skipping camera shake here — shake reads as 'something hit me', wrong feeling for pickups. Same for heavy ducking. Want a tiny duck (0.2) to make the pickup chime pop?"
|
|
79
|
+
- Does NOT call `add_trauma` from the pickup handler.
|
|
68
80
|
|
|
69
81
|
**Assertions:**
|
|
70
82
|
|
|
71
|
-
- [ ] Skill
|
|
72
|
-
- [ ] Skill
|
|
73
|
-
- [ ]
|
|
83
|
+
- [ ] Skill recognizes pickups ≠ combat and adapts the trio.
|
|
84
|
+
- [ ] Skill explicitly skips camera-shake with reasoning, not silently.
|
|
85
|
+
- [ ] HitFlash script is reused (not a forked copy) — `flash()` called on the pickup mesh.
|
|
86
|
+
- [ ] Audio duck `amount` ≤ 0.3, duration ≤ 0.4 (gentle).
|
|
87
|
+
- [ ] Skill does NOT install the full combat trio when the answer was "pickups".
|
|
74
88
|
|
|
75
89
|
## Case 4: No Summer MCP — file-edit fallback
|
|
76
90
|
|
|
77
91
|
**Fixture:** Same as Case 1, but Summer MCP is unavailable (Cursor in a project where the engine is not connected).
|
|
78
92
|
|
|
79
|
-
**Input:** "Add
|
|
93
|
+
**Input:** "Add hit-flash + camera-shake + audio ducking to my combat."
|
|
80
94
|
|
|
81
95
|
**Expected behavior:**
|
|
82
96
|
|
|
83
97
|
- Skill detects MCP unavailable.
|
|
84
|
-
- Asks the user to paste the relevant `.tscn` snippet
|
|
85
|
-
- Writes `scripts/hit_flash.gd` directly via host file tools.
|
|
86
|
-
- Provides a `.tscn` patch
|
|
87
|
-
-
|
|
98
|
+
- Asks the user to paste (a) the relevant `.tscn` snippet showing Enemy + Player + Camera3D node paths, and (b) the bus list from `default_bus_layout.tres`.
|
|
99
|
+
- Writes `scripts/vfx/hit_flash.gd`, `scripts/vfx/camera_shake.gd`, `scripts/vfx/audio_ducker.gd` directly via host file tools.
|
|
100
|
+
- Provides a `.tscn` patch for adding the HitFlash node and a manual instruction for registering the AudioDucker autoload via `project.godot` or the editor.
|
|
101
|
+
- Provides a manual signal-connect instruction (or a `.tscn` connection block) instead of `summer_connect_signal`.
|
|
102
|
+
- Still asks "May I write `scripts/vfx/<file>.gd`?" before each file write.
|
|
103
|
+
- Does NOT blindly call `summer_*` tools.
|
|
88
104
|
|
|
89
105
|
**Assertions:**
|
|
90
106
|
|
|
91
|
-
- [ ] Skill identifies MCP
|
|
92
|
-
- [ ] Generated GDScript is syntactically valid Godot 4
|
|
93
|
-
- [ ] Skill asks the user to paste the
|
|
94
|
-
- [ ] Skill
|
|
107
|
+
- [ ] Skill identifies MCP unavailable and adapts.
|
|
108
|
+
- [ ] Generated GDScript is syntactically valid Godot 4.5 with type hints.
|
|
109
|
+
- [ ] Skill asks the user to paste the scene snippet AND the bus list.
|
|
110
|
+
- [ ] Skill provides explicit autoload-registration instructions (no `summer_*` autoload tool exists).
|
|
111
|
+
- [ ] Skill applies "May I write …" protocol on each of the 3 file writes.
|
|
112
|
+
- [ ] No `summer_*` tool calls appear in the transcript when MCP is flagged unavailable.
|
|
95
113
|
|
|
96
114
|
---
|
|
97
115
|
|