summer-engine 2.6.6 → 2.8.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 +1 -1
- package/.claude-plugin/plugin.json +4 -1
- package/.codex-plugin/plugin.json +6 -2
- package/.cursor-plugin/plugin.json +5 -1
- package/.opencode/INSTALL.md +1 -1
- package/.opencode/plugins/summer.js +2 -2
- package/AGENTS.md +11 -7
- package/CHANGELOG.md +40 -0
- package/GEMINI.md +9 -7
- package/README.md +63 -21
- package/_persona/summer/SKILL.md +1 -0
- package/assets/autopilot/README.md +51 -0
- package/assets/autopilot/autopilot.gd +222 -0
- package/assets/autopilot/probe_base.gd +262 -0
- package/assets/autopilot/run.sh +78 -0
- package/commands/gameskill.md +11 -2
- package/commands/summer.md +13 -0
- package/dist/bin/summer.js +12 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +53 -0
- package/dist/commands/create.d.ts +1 -0
- package/dist/commands/create.js +38 -6
- package/dist/commands/debug.d.ts +2 -0
- package/dist/commands/debug.js +44 -0
- package/dist/commands/doctor.js +112 -8
- package/dist/commands/list.js +1 -1
- package/dist/commands/login.d.ts +19 -0
- package/dist/commands/login.js +123 -36
- package/dist/commands/logout.js +3 -16
- package/dist/commands/logs.d.ts +2 -0
- package/dist/commands/logs.js +19 -0
- package/dist/commands/mcp.js +7 -2
- package/dist/commands/open.js +1 -1
- package/dist/commands/publish.d.ts +2 -0
- package/dist/commands/publish.js +20 -0
- package/dist/commands/releases.d.ts +2 -0
- package/dist/commands/releases.js +20 -0
- package/dist/commands/run.js +1 -1
- package/dist/commands/skills.js +1 -1
- package/dist/lib/api-client.d.ts +15 -4
- package/dist/lib/api-client.js +138 -13
- package/dist/lib/async-op-lifecycle.d.ts +7 -2
- package/dist/lib/async-op-lifecycle.js +32 -9
- package/dist/lib/auth.d.ts +40 -12
- package/dist/lib/auth.js +173 -37
- package/dist/lib/cloud/engine-bridge.d.ts +17 -4
- package/dist/lib/cloud/engine-bridge.js +32 -6
- package/dist/lib/config.d.ts +20 -0
- package/dist/lib/config.js +142 -0
- package/dist/lib/creator.d.ts +93 -0
- package/dist/lib/creator.js +393 -0
- package/dist/lib/debug-report.d.ts +50 -0
- package/dist/lib/debug-report.js +308 -0
- package/dist/lib/engine.d.ts +35 -2
- package/dist/lib/engine.js +240 -6
- package/dist/lib/game-task-plan.js +4 -4
- package/dist/lib/mcp-boot-notice.d.ts +3 -0
- package/dist/lib/mcp-boot-notice.js +7 -0
- package/dist/lib/mcp-log.d.ts +3 -0
- package/dist/lib/mcp-log.js +72 -0
- package/dist/lib/public-surface-paths.d.ts +13 -0
- package/dist/lib/public-surface-paths.js +42 -0
- package/dist/lib/skills-registry.d.ts +33 -1
- package/dist/lib/skills-registry.js +55 -0
- package/dist/lib/store.d.ts +14 -0
- package/dist/lib/store.js +145 -0
- package/dist/lib/summer-compatibility.d.ts +6 -0
- package/dist/lib/summer-compatibility.js +22 -0
- package/dist/mcp/server.d.ts +10 -3
- package/dist/mcp/server.js +104 -11
- package/dist/mcp/tools/asset-tools.js +33 -12
- package/dist/mcp/tools/cloud-tools.js +15 -15
- package/dist/mcp/tools/creator-tools.d.ts +2 -0
- package/dist/mcp/tools/creator-tools.js +105 -0
- package/dist/mcp/tools/debug-tools.js +44 -1
- package/dist/mcp/tools/file-tools.d.ts +2 -0
- package/dist/mcp/tools/file-tools.js +154 -0
- package/dist/mcp/tools/generate-tools.js +159 -11
- package/dist/mcp/tools/project-tools.js +37 -27
- package/dist/mcp/tools/scene-tools.js +106 -29
- package/dist/mcp/tools/visual-tools.js +4 -3
- package/dist/mcp/tools/with-engine.js +4 -4
- package/hooks/session-start.sh +5 -5
- package/package.json +3 -1
- package/references/collaborative-protocol.md +50 -0
- package/references/gd-style.md +121 -0
- package/references/godot-version.md +51 -0
- package/references/mcp-tools-reference.md +199 -0
- package/references/public-surface-language.md +30 -0
- package/references/summer-folder.md +90 -0
- package/references/template-registry.md +73 -0
- package/skills/2d-assets/character-portrait/SKILL.md +17 -12
- package/skills/2d-assets/concept-art/SKILL.md +10 -9
- package/skills/2d-assets/create-asset-sheet/SKILL.md +17 -15
- package/skills/2d-assets/pixel-art/SKILL.md +36 -20
- package/skills/2d-assets/skybox-panorama/SKILL.md +32 -37
- package/skills/2d-assets/sprite-sheet/SKILL.md +40 -35
- package/skills/2d-assets/tileable-texture/SKILL.md +28 -22
- package/skills/2d-assets/ui-graphics/SKILL.md +46 -32
- package/skills/2d-assets/use-widget-asset/SKILL.md +8 -6
- package/skills/3d-assets/character-model/SKILL.md +34 -19
- package/skills/3d-assets/environment-kit/SKILL.md +11 -5
- package/skills/3d-assets/organic-model/SKILL.md +8 -5
- package/skills/3d-assets/prop-model/SKILL.md +9 -3
- package/skills/3d-assets/vehicle-model/SKILL.md +32 -19
- package/skills/README.md +1 -1
- package/skills/ai-and-npcs/design-npc/SKILL.md +31 -13
- package/skills/animation/animation-tree/SKILL.md +39 -15
- package/skills/animation/facial-and-lipsync/SKILL.md +25 -8
- package/skills/animation/generate-motion/SKILL.md +47 -15
- package/skills/animation/procedural-animation/SKILL.md +31 -13
- package/skills/animation/retarget/SKILL.md +127 -79
- package/skills/audio/adaptive-music/SKILL.md +24 -20
- package/skills/audio/ambient-bed/SKILL.md +22 -16
- package/skills/audio/audio-direction/SKILL.md +15 -10
- package/skills/audio/music-track/SKILL.md +18 -12
- package/skills/audio/sound-effect/SKILL.md +17 -12
- package/skills/audio/voice-line/SKILL.md +42 -42
- package/skills/character-controllers/fps-controller/SKILL.md +26 -16
- package/skills/debugging/debug/SKILL.md +74 -20
- package/skills/deployment/export-and-ship/SKILL.md +105 -38
- package/skills/deployment/remote-deploy/SKILL.md +140 -0
- package/skills/gameplay-mechanics/auto-fire-targeting/SKILL.md +26 -1
- package/skills/gameplay-mechanics/design-mechanic/SKILL.md +23 -15
- package/skills/level-design/design-level/SKILL.md +22 -8
- package/skills/level-design/scene-to-level/SKILL.md +13 -7
- package/skills/multiplayer-and-networking/host-authoritative-state/SKILL.md +8 -8
- package/skills/multiplayer-and-networking/peer-to-peer-multiplayer/SKILL.md +2 -7
- package/skills/multiplayer-and-networking/setup-multiplayer/SKILL.md +26 -18
- package/skills/performance/tune-performance/SKILL.md +51 -32
- package/skills/rendering-and-lighting/3d-lighting/SKILL.md +34 -5
- package/skills/rendering-and-lighting/art-direction/SKILL.md +6 -8
- package/skills/scene-and-project/brainstorm-game/SKILL.md +7 -9
- package/skills/scene-and-project/make-game/SKILL.md +2 -1
- package/skills/scene-and-project/play/SKILL.md +10 -4
- package/skills/scene-and-project/scene-composition/SKILL.md +21 -8
- package/skills/scene-and-project/summer-cloud/SKILL.md +92 -0
- package/skills/scripting-patterns/gdscript-patterns/SKILL.md +1 -1
- package/skills/ui-and-ux/ui-basics/SKILL.md +16 -7
- package/skills/video/animated-loop/SKILL.md +63 -39
- package/skills/video/cinematic-cutscene/SKILL.md +66 -30
- package/skills/video/trailer-shot/SKILL.md +30 -21
- package/skills/visual-effects/_building-blocks/additive-billboard-particles.md +25 -16
- package/skills/visual-effects/_building-blocks/trauma-shake-snippet.md +5 -3
- package/skills/visual-effects/game-feel/SKILL.md +51 -33
- package/skills/visual-effects/recipes/dissolve/SKILL.md +51 -9
- package/skills/visual-effects/recipes/fire/SKILL.md +136 -49
- package/skills/visual-effects/recipes/hit-spark/SKILL.md +45 -8
- package/skills/visual-effects/recipes/lightning/SKILL.md +59 -27
- package/skills/visual-effects/recipes/magic-glow/SKILL.md +59 -26
- package/skills/visual-effects/recipes/muzzle-flash/SKILL.md +68 -25
- package/skills/visual-effects/recipes/smoke/SKILL.md +89 -28
- package/skills/visual-effects/recipes/water-ripple/SKILL.md +83 -23
- package/skills/workflow/brainstorming/SKILL.md +1 -1
- package/skills/workflow/debugging-game-feel/SKILL.md +29 -9
- package/skills/workflow/diagnosing-perf-regressions/SKILL.md +46 -21
- package/skills/workflow/gameskill/SKILL.md +11 -2
- package/skills/workflow/headless-scripting/SKILL.md +407 -0
- package/skills/workflow/investigating-bugs/SKILL.md +4 -2
- package/skills/workflow/mcpupdate/SKILL.md +9 -9
- package/skills/workflow/playtesting-a-feature/SKILL.md +94 -21
- package/skills/workflow/skill-create/SKILL.md +7 -7
- package/skills/workflow/skill-test/SKILL.md +3 -3
- package/skills/workflow/using-summer/SKILL.md +32 -3
- package/skills/workflow/verification-before-completion/SKILL.md +2 -0
- package/skills/workflow/writing-plans/SKILL.md +7 -7
- package/skills/workflow/writing-skills/SKILL.md +7 -5
- package/skills/workflow/writing-skills/testing-skills-with-subagents.md +1 -1
|
@@ -2,6 +2,27 @@ import { z } from "zod";
|
|
|
2
2
|
import { withEngine } from "./with-engine.js";
|
|
3
3
|
import { readFile } from "fs/promises";
|
|
4
4
|
import { join } from "path";
|
|
5
|
+
function sceneMutationOps(ops) {
|
|
6
|
+
const saveIndexes = ops
|
|
7
|
+
.map((op, index) => op.op === "SaveScene" ? index : -1)
|
|
8
|
+
.filter((index) => index >= 0);
|
|
9
|
+
if (saveIndexes.length > 1) {
|
|
10
|
+
throw new Error("A scene mutation batch may contain only one SaveScene");
|
|
11
|
+
}
|
|
12
|
+
if (saveIndexes.length === 1) {
|
|
13
|
+
if (saveIndexes[0] !== ops.length - 1) {
|
|
14
|
+
throw new Error("SaveScene must be the final operation in a scene mutation batch");
|
|
15
|
+
}
|
|
16
|
+
return ops;
|
|
17
|
+
}
|
|
18
|
+
return [...ops, { op: "SaveScene" }];
|
|
19
|
+
}
|
|
20
|
+
function executeSceneMutation(client, scenePath, ops, options) {
|
|
21
|
+
return client.executeIdentityBoundOps(sceneMutationOps(ops), {
|
|
22
|
+
...(options ?? {}),
|
|
23
|
+
scenePath,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
5
26
|
async function readMainSceneFromProject(projectPath) {
|
|
6
27
|
if (!projectPath)
|
|
7
28
|
return null;
|
|
@@ -14,6 +35,20 @@ async function readMainSceneFromProject(projectPath) {
|
|
|
14
35
|
return null;
|
|
15
36
|
}
|
|
16
37
|
}
|
|
38
|
+
function requireSuccessfulOps(result, context) {
|
|
39
|
+
const receipt = (result ?? {});
|
|
40
|
+
const results = Array.isArray(receipt.results)
|
|
41
|
+
? receipt.results
|
|
42
|
+
: [];
|
|
43
|
+
const failed = results.find((entry) => entry?.ok === false);
|
|
44
|
+
if (receipt.status === "error" || failed) {
|
|
45
|
+
const error = (typeof failed?.error === "string" && failed.error) ||
|
|
46
|
+
(typeof receipt.error === "string" && receipt.error) ||
|
|
47
|
+
`${context} failed`;
|
|
48
|
+
throw new Error(error);
|
|
49
|
+
}
|
|
50
|
+
return receipt;
|
|
51
|
+
}
|
|
17
52
|
export function registerSceneTools(server) {
|
|
18
53
|
server.tool("summer_create_scene", `Create a new empty scene file safely.
|
|
19
54
|
|
|
@@ -45,19 +80,22 @@ Recommended workflow:
|
|
|
45
80
|
throw new Error("No scene open and could not resolve main scene. Call summer_get_project_context first, then open a known scene.");
|
|
46
81
|
}
|
|
47
82
|
await client.executeOps([{ op: "OpenScene", path: templateScene }]);
|
|
48
|
-
const tree = (await client.getSceneState());
|
|
83
|
+
const tree = (await client.getSceneState(templateScene));
|
|
49
84
|
const children = tree.data?.children ?? tree.children ?? [];
|
|
50
85
|
const removeOps = children
|
|
51
86
|
.map((c) => c.path)
|
|
52
87
|
.filter((p) => typeof p === "string" && p.length > 0)
|
|
53
88
|
.map((p) => ({ op: "RemoveNode", path: `./${p}` }));
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
89
|
+
const createOps = [
|
|
90
|
+
...removeOps,
|
|
91
|
+
{ op: "SetProp", path: ".", key: "name", value: rootName },
|
|
92
|
+
{ op: "SaveScene", path },
|
|
93
|
+
];
|
|
94
|
+
const createReceipt = requireSuccessfulOps(await executeSceneMutation(client, templateScene, createOps, {
|
|
95
|
+
groupUndo: true,
|
|
96
|
+
}), `Creating ${path}`);
|
|
59
97
|
if (currentScene && currentScene !== path) {
|
|
60
|
-
await client.executeOps([{ op: "OpenScene", path: currentScene }]);
|
|
98
|
+
requireSuccessfulOps(await client.executeOps([{ op: "OpenScene", path: currentScene }]), `Restoring ${currentScene}`);
|
|
61
99
|
}
|
|
62
100
|
return {
|
|
63
101
|
ok: true,
|
|
@@ -65,14 +103,13 @@ Recommended workflow:
|
|
|
65
103
|
rootName,
|
|
66
104
|
templateScene,
|
|
67
105
|
restoredScene: currentScene,
|
|
106
|
+
receipt: createReceipt,
|
|
68
107
|
};
|
|
69
108
|
}));
|
|
70
109
|
server.tool("summer_add_node", `Add a new node to the scene tree.
|
|
71
110
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
2) summer_open_main_scene (if no scene open)
|
|
75
|
-
3) summer_get_scene_tree
|
|
111
|
+
Pass the exact res:// scenePath to mutate. The scene does not need to be the
|
|
112
|
+
active editor tab.
|
|
76
113
|
|
|
77
114
|
Common node types:
|
|
78
115
|
- 3D: Node3D, MeshInstance3D, CharacterBody3D, RigidBody3D, StaticBody3D, Camera3D, DirectionalLight3D, OmniLight3D, SpotLight3D, WorldEnvironment, CollisionShape3D, Area3D
|
|
@@ -81,10 +118,11 @@ Common node types:
|
|
|
81
118
|
- Audio: AudioStreamPlayer, AudioStreamPlayer3D
|
|
82
119
|
|
|
83
120
|
The parent path uses "./" prefix for relative paths from scene root. E.g., "./World" means the "World" child of the root node.`, {
|
|
121
|
+
scenePath: z.string().describe("Target scene path, e.g. 'res://main.tscn'"),
|
|
84
122
|
parent: z.string().describe("Parent node path, e.g. './World' or './World/Enemies'"),
|
|
85
|
-
type: z.string().describe("
|
|
123
|
+
type: z.string().describe("Summer Engine node type, e.g. 'MeshInstance3D', 'CharacterBody3D'"),
|
|
86
124
|
name: z.string().describe("Name for the new node, e.g. 'Player', 'MainCamera'"),
|
|
87
|
-
}, async ({ parent, type, name }) => withEngine(async (client) => client
|
|
125
|
+
}, async ({ scenePath, parent, type, name }) => withEngine(async (client) => executeSceneMutation(client, scenePath, [{ op: "AddNode", parent, type, name }])));
|
|
88
126
|
server.tool("summer_set_prop", `Set a property on a node. This is the primary way to configure nodes after adding them.
|
|
89
127
|
|
|
90
128
|
VALUE FORMAT — Godot string syntax for complex types:
|
|
@@ -106,29 +144,37 @@ COMMON PROPERTIES:
|
|
|
106
144
|
- shadow_enabled: true — for lights
|
|
107
145
|
- light_energy: 1.5 — light intensity
|
|
108
146
|
- fov: 75.0 — camera field of view`, {
|
|
147
|
+
scenePath: z.string().describe("Target scene path, e.g. 'res://main.tscn'"),
|
|
109
148
|
path: z.string().describe("Node path, e.g. './World/Player'"),
|
|
110
149
|
key: z.string().describe("Property name, e.g. 'position', 'mesh', 'visible'"),
|
|
111
|
-
value: z.union([z.string(), z.number(), z.boolean()]).describe("Value in
|
|
112
|
-
}, async ({ path, key, value }) => withEngine(async (client) => client
|
|
150
|
+
value: z.union([z.string(), z.number(), z.boolean()]).describe("Value in Summer Engine variant-string format for complex types, native JSON for primitives"),
|
|
151
|
+
}, async ({ scenePath, path, key, value }) => withEngine(async (client) => executeSceneMutation(client, scenePath, [{ op: "SetProp", path, key, value }])));
|
|
113
152
|
server.tool("summer_set_resource_property", `Set a nested property on a resource attached to a node.
|
|
114
153
|
|
|
115
154
|
Use when you need to modify a sub-property of a resource, like:
|
|
116
155
|
- CollisionShape3D shape size: nodePath="./Player/CollisionShape3D", resourceProperty="shape", subProperty="size", value="Vector3(1, 2, 1)"
|
|
117
156
|
- Material albedo color: nodePath="./Floor", resourceProperty="material_override", subProperty="albedo_color", value="Color(0.2, 0.5, 0.2, 1)"
|
|
118
157
|
- Mesh size: nodePath="./Box", resourceProperty="mesh", subProperty="size", value="Vector3(2, 2, 2)"`, {
|
|
158
|
+
scenePath: z.string().describe("Target scene path, e.g. 'res://main.tscn'"),
|
|
119
159
|
nodePath: z.string().describe("Node path, e.g. './Player/CollisionShape3D'"),
|
|
120
160
|
resourceProperty: z.string().describe("Resource property on the node, e.g. 'shape', 'mesh', 'material_override'"),
|
|
121
161
|
subProperty: z.string().describe("Property on the resource, e.g. 'size', 'radius', 'albedo_color'"),
|
|
122
|
-
value: z.union([z.string(), z.number(), z.boolean()]).describe("Value in
|
|
123
|
-
}, async ({ nodePath, resourceProperty, subProperty, value }) => withEngine(async (client) => client
|
|
162
|
+
value: z.union([z.string(), z.number(), z.boolean()]).describe("Value in Summer Engine variant-string format"),
|
|
163
|
+
}, async ({ scenePath, nodePath, resourceProperty, subProperty, value }) => withEngine(async (client) => executeSceneMutation(client, scenePath, [
|
|
124
164
|
{ op: "SetResourceProperty", nodePath, resourceProperty, subProperty, value },
|
|
125
165
|
])));
|
|
126
|
-
server.tool("summer_remove_node", "Remove a node from the scene tree. All children are removed too. Cannot remove the root node. Supports undo. Destructive operation: do not delete multiple top-level nodes unless the user explicitly requests destructive changes.", {
|
|
127
|
-
|
|
166
|
+
server.tool("summer_remove_node", "Remove a node from the scene tree. All children are removed too. Cannot remove the root node. Supports undo. Destructive operation: do not delete multiple top-level nodes unless the user explicitly requests destructive changes.", {
|
|
167
|
+
scenePath: z.string().describe("Target scene path, e.g. 'res://main.tscn'"),
|
|
168
|
+
path: z.string().describe("Node path to remove, e.g. './World/OldEnemy'"),
|
|
169
|
+
}, async ({ scenePath, path }) => withEngine(async (client) => executeSceneMutation(client, scenePath, [{ op: "RemoveNode", path }])));
|
|
170
|
+
server.tool("summer_save_scene", "Save an explicit scene to disk. Mutation tools already append one save; use this for a standalone save or save-as.", {
|
|
171
|
+
scenePath: z.string().describe("Scene to save, e.g. 'res://main.tscn'"),
|
|
172
|
+
path: z.string().optional().describe("Optional save-as path, e.g. 'res://levels/level2.tscn'"),
|
|
173
|
+
}, async ({ scenePath, path }) => withEngine(async (client) => {
|
|
128
174
|
const op = { op: "SaveScene" };
|
|
129
175
|
if (path)
|
|
130
176
|
op.path = path;
|
|
131
|
-
return client
|
|
177
|
+
return executeSceneMutation(client, scenePath, [op]);
|
|
132
178
|
}));
|
|
133
179
|
server.tool("summer_open_scene", `Open a scene file in the editor. Use this to switch between scenes.
|
|
134
180
|
|
|
@@ -142,14 +188,15 @@ Do not guess paths. Prefer:
|
|
|
142
188
|
- Compose scenes from smaller scenes (e.g., add a "Player" scene into a "Level" scene)
|
|
143
189
|
|
|
144
190
|
The scene must already exist in the project. Use summer_import_from_url first if importing from external sources.`, {
|
|
191
|
+
scenePath: z.string().describe("Target scene to receive the instance, e.g. 'res://main.tscn'"),
|
|
145
192
|
parent: z.string().describe("Parent node path, e.g. './World'"),
|
|
146
193
|
scene: z.string().describe("Scene/model path, e.g. 'res://player.tscn' or 'res://models/tree.glb'"),
|
|
147
194
|
name: z.string().optional().describe("Override the instance name"),
|
|
148
|
-
}, async ({ parent, scene, name }) => withEngine(async (client) => {
|
|
195
|
+
}, async ({ scenePath, parent, scene, name }) => withEngine(async (client) => {
|
|
149
196
|
const op = { op: "InstantiateScene", parent, scene };
|
|
150
197
|
if (name)
|
|
151
198
|
op.name = name;
|
|
152
|
-
return client
|
|
199
|
+
return executeSceneMutation(client, scenePath, [op]);
|
|
153
200
|
}));
|
|
154
201
|
server.tool("summer_connect_signal", `Connect a signal between two nodes. Signals are Godot's event system — they notify when something happens.
|
|
155
202
|
|
|
@@ -161,11 +208,12 @@ Common signals:
|
|
|
161
208
|
- "input_event" — CollisionObject received input
|
|
162
209
|
|
|
163
210
|
The receiver node must have a script with the specified method.`, {
|
|
211
|
+
scenePath: z.string().describe("Target scene path, e.g. 'res://main.tscn'"),
|
|
164
212
|
emitter: z.string().describe("Node that fires the signal, e.g. './Player/HitArea'"),
|
|
165
213
|
signal: z.string().describe("Signal name, e.g. 'body_entered'"),
|
|
166
214
|
receiver: z.string().describe("Node with the handler script, e.g. './Player'"),
|
|
167
215
|
method: z.string().describe("Method name in the receiver's script, e.g. '_on_hit_area_body_entered'"),
|
|
168
|
-
}, async ({ emitter, signal, receiver, method }) => withEngine(async (client) => client
|
|
216
|
+
}, async ({ scenePath, emitter, signal, receiver, method }) => withEngine(async (client) => executeSceneMutation(client, scenePath, [
|
|
169
217
|
{ op: "ConnectSignal", emitter, signal, receiver, method },
|
|
170
218
|
])));
|
|
171
219
|
server.tool("summer_select_node", "Select a node in the editor's scene tree and show it in the inspector panel. Useful for focusing the editor on a specific node.", {
|
|
@@ -178,16 +226,17 @@ The receiver node must have a script with the specified method.`, {
|
|
|
178
226
|
return client.executeOps([op]);
|
|
179
227
|
}));
|
|
180
228
|
server.tool("summer_replace_node", "Replace a node with a different type or scene, preserving its position in the tree and its children. Useful for changing a StaticBody3D to a RigidBody3D, or swapping a placeholder with a proper prefab.", {
|
|
229
|
+
scenePath: z.string().describe("Target scene path, e.g. 'res://main.tscn'"),
|
|
181
230
|
path: z.string().describe("Node path to replace"),
|
|
182
231
|
type: z.string().optional().describe("New node type, e.g. 'RigidBody3D'"),
|
|
183
232
|
scene: z.string().optional().describe("Scene to replace with, e.g. 'res://enemies/boss.tscn'"),
|
|
184
|
-
}, async ({ path, type, scene }) => withEngine(async (client) => {
|
|
233
|
+
}, async ({ scenePath, path, type, scene }) => withEngine(async (client) => {
|
|
185
234
|
const op = { op: "ReplaceNode", path };
|
|
186
235
|
if (type)
|
|
187
236
|
op.type = type;
|
|
188
237
|
if (scene)
|
|
189
238
|
op.scene = scene;
|
|
190
|
-
return client
|
|
239
|
+
return executeSceneMutation(client, scenePath, [op]);
|
|
191
240
|
}));
|
|
192
241
|
server.tool("summer_inspect_node", `Get all editable properties of a node with their current values, types, and resource info.
|
|
193
242
|
|
|
@@ -211,9 +260,37 @@ Each op in the array uses the same format as the individual tools:
|
|
|
211
260
|
- {"op": "SetProp", "path": "Floor", "key": "mesh", "value": "PlaneMesh"}
|
|
212
261
|
- {"op": "SetResourceProperty", "nodePath": "Floor", "resourceProperty": "mesh", "subProperty": "size", "value": "Vector2(20, 20)"}
|
|
213
262
|
|
|
214
|
-
RAW RUNTIME OPS (interactive verification —
|
|
215
|
-
-
|
|
216
|
-
-
|
|
263
|
+
RAW RUNTIME OPS (interactive verification — structured failure_reason passes through verbatim):
|
|
264
|
+
- RunVerification — spawn a hidden, disposable game instance that runs a GDScript probe and dies (never touches the editor): {"op": "RunVerification", "probe_source": "extends SummerProbeBase\\nfunc _ready(): await super._ready(); report('ok', true); finish()", "max_seconds": 20}. Returns {ok, results, frames, out_dir}. Probe API: report()/save_frame()/press()/key()/finish(). This is the ONLY way to drive input from MCP, and unlike the editor it renders real pixels, so save_frame() produces a real image.
|
|
265
|
+
- SimulateInput is NOT reachable from MCP or the CLI. It requires the in-editor chat bridge's async reply channel; every queued caller gets {"ok": false, "failure_reason": "unsupported_transport"} on every engine build. Do not send it and do not treat that reply as a version problem — use RunVerification's press()/key() instead.
|
|
266
|
+
|
|
267
|
+
Do not mix OpenScene with scene mutations in one batch. OpenScene is a UI action;
|
|
268
|
+
send it separately. scenePath selects every mutation target. The tool appends one
|
|
269
|
+
final SaveScene when the batch mutates a scene; if supplied explicitly, SaveScene
|
|
270
|
+
must appear exactly once and be the final operation.`, {
|
|
271
|
+
scenePath: z.string().optional().describe("Required when ops contains scene mutations; exact res:// target scene path"),
|
|
217
272
|
ops: z.array(z.record(z.unknown())).describe("Array of operation objects, each with 'op' plus its parameters"),
|
|
218
|
-
}, async ({ ops }) => withEngine(async (client) =>
|
|
273
|
+
}, async ({ scenePath, ops }) => withEngine(async (client) => {
|
|
274
|
+
const rawFileMutation = ops.find((op) => {
|
|
275
|
+
const kind = String(op.op ?? "");
|
|
276
|
+
return kind === "WriteFile" || kind === "ReplaceText";
|
|
277
|
+
});
|
|
278
|
+
if (rawFileMutation) {
|
|
279
|
+
throw new Error(`summer_batch does not accept raw ${String(rawFileMutation.op)} operations. ` +
|
|
280
|
+
"Use summer_write_file or summer_replace_text so project identity, content guards, and same-file ordering are enforced.");
|
|
281
|
+
}
|
|
282
|
+
const sceneMutations = new Set([
|
|
283
|
+
"AddNode", "RemoveNode", "MoveNode", "ReparentNode", "ReplaceNode",
|
|
284
|
+
"SetProp", "SetResourceProperty", "ConnectSignal", "DisconnectSignal",
|
|
285
|
+
"InstantiateScene", "SaveScene", "Undo",
|
|
286
|
+
]);
|
|
287
|
+
const needsScenePath = ops.some((op) => sceneMutations.has(String(op.op ?? "")));
|
|
288
|
+
if (needsScenePath && !scenePath) {
|
|
289
|
+
throw new Error("summer_batch requires scenePath when ops contains scene mutations");
|
|
290
|
+
}
|
|
291
|
+
const options = { groupUndo: true, ...(scenePath ? { scenePath } : {}) };
|
|
292
|
+
return needsScenePath
|
|
293
|
+
? executeSceneMutation(client, scenePath, ops, options)
|
|
294
|
+
: client.executeOps(ops, options);
|
|
295
|
+
}));
|
|
219
296
|
}
|
|
@@ -10,14 +10,15 @@ import { withEngine } from "./with-engine.js";
|
|
|
10
10
|
export function registerVisualTools(server) {
|
|
11
11
|
server.tool("summer_screenshot", `Capture a frame from Summer Engine and return it as an image you can look at directly.
|
|
12
12
|
|
|
13
|
-
Use this to visually verify your work: scene layout, asset placement, scale, framing,
|
|
13
|
+
Use this to visually verify your work: scene layout, asset placement, scale, framing, missing/untextured assets, or runtime gameplay state. You see the actual pixels — no description layer in between. Lighting and materials are only truthfully shown by the "viewport" and "game" targets — see the note on "scene" below.
|
|
14
14
|
|
|
15
15
|
target:
|
|
16
16
|
"viewport" (default) — the editor's CURRENT view (whatever scene/tab is open). No game boot. Use for edit-time checks of how the scene looks right now.
|
|
17
|
-
"scene" — an OFFSCREEN render of a scene file (no game boot; physics/particles/animations are static at t=0). Optionally pass scenePath/framing/size/nodePath. Use for
|
|
17
|
+
"scene" — an OFFSCREEN render of a scene file (no game boot; physics/particles/animations are static at t=0). Optionally pass scenePath/framing/size/nodePath. Use for COMPOSITION, SCALE and FRAMING without touching the editor's open tab.
|
|
18
|
+
It does NOT use the scene's environment/sky, and it injects a synthetic camera and light when the scene has none. The scene's WorldEnvironment — sky, fog, tonemap, glow, SSAO, ambient — is replaced by a flat preview environment. So this target CANNOT verify lighting, mood, or any material property that depends on the environment: change them and the frame comes back identical. For those, boot the game or run a RunVerification probe, whose instance renders the real environment.
|
|
18
19
|
"game" — a frame from the RUNNING game (real runtime state). Start the game first (summer_play). Not available over a plain local connection — needs the Summer desktop app bridge.
|
|
19
20
|
|
|
20
|
-
Static frame only — one moment, not motion.
|
|
21
|
+
Static frame only — one moment, not motion. For a SEQUENCE of frames over time, or for anything lighting-dependent when the desktop bridge is unavailable, use a RunVerification probe's save_frame() — its instance has a real renderer.`, {
|
|
21
22
|
target: z
|
|
22
23
|
.enum(["viewport", "scene", "game"])
|
|
23
24
|
.optional()
|
|
@@ -19,7 +19,10 @@ const SUCCESS_TERMINAL_STATES = new Set(["applied", "no_op"]);
|
|
|
19
19
|
// `error` string (queue-full / lease-reject / identity-mismatch / no-progress
|
|
20
20
|
// timeout frequently arrive with terminalState set and results[] absent).
|
|
21
21
|
const TERMINAL_STATE_MESSAGES = {
|
|
22
|
-
timed_out: "Engine operation timed out
|
|
22
|
+
timed_out: "Engine operation timed out. Its final state is unknown; inspect the target before retrying.",
|
|
23
|
+
still_queued: "Summer Engine accepted the operation, but it was still queued when the client stopped waiting. It may still run; do not retry blindly.",
|
|
24
|
+
still_running: "Summer Engine accepted and started the operation, but no final receipt arrived. It may still be running or may already have applied; inspect the target before retrying.",
|
|
25
|
+
uncertain: "Summer Engine did not provide a final operation receipt. The current state is uncertain; inspect the target before retrying.",
|
|
23
26
|
not_connected: "Summer Engine is not connected (terminalState: not_connected). Nothing was applied.",
|
|
24
27
|
identity_mismatch: "Operation rejected — wrong project/instance (terminalState: identity_mismatch). Nothing was mutated.",
|
|
25
28
|
content_mismatch: "Operation rejected — content changed since last read (terminalState: content_mismatch). Nothing was applied.",
|
|
@@ -117,9 +120,6 @@ function buildActionHint(message) {
|
|
|
117
120
|
if (normalized.includes("failed to open scene")) {
|
|
118
121
|
return "Scene path could not be opened. Call `summer_get_project_context` to get `mainScene`, then open that exact path. Avoid guessing scene filenames.";
|
|
119
122
|
}
|
|
120
|
-
if (normalized.includes("writefile cannot edit .tscn/.scn")) {
|
|
121
|
-
return "Write .gd/.cs/.json/docs/simple config files with normal file-edit tools. Use Summer MCP for live scene state, inspector/node edits, imports, play/stop, diagnostics, and visual verification.";
|
|
122
|
-
}
|
|
123
123
|
return null;
|
|
124
124
|
}
|
|
125
125
|
export async function withEngine(fn, opts) {
|
package/hooks/session-start.sh
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
# Event: SessionStart (matcher: startup|clear|compact)
|
|
5
5
|
# Purpose: Orient Claude on every fresh Summer-enabled session.
|
|
6
|
-
# Detect
|
|
6
|
+
# Detect Summer project + GameSoul + doctor health, surface a one-line
|
|
7
7
|
# Bob-style greeting as additional context.
|
|
8
8
|
#
|
|
9
9
|
# Input: JSON on stdin with { session_id, source, model, cwd, ... }
|
|
@@ -36,7 +36,7 @@ else
|
|
|
36
36
|
LINES+=("Summer ready.")
|
|
37
37
|
fi
|
|
38
38
|
|
|
39
|
-
# Line 2:
|
|
39
|
+
# Line 2: Summer project + GameSoul one-liner (only if project.godot exists)
|
|
40
40
|
if [ -f "${PROJECT_DIR}/project.godot" ]; then
|
|
41
41
|
PROJECT_NAME=$(grep -E '^config/name=' "${PROJECT_DIR}/project.godot" 2>/dev/null \
|
|
42
42
|
| head -1 | sed 's/^config\/name=//;s/^"//;s/"$//')
|
|
@@ -48,12 +48,12 @@ if [ -f "${PROJECT_DIR}/project.godot" ]; then
|
|
|
48
48
|
SOUL_LINE=$(awk 'BEGIN{p=""} /^[^#[:space:]]/ && NF>0 {p=$0; exit} END{print p}' \
|
|
49
49
|
"$SOUL_FILE" 2>/dev/null | cut -c1-120)
|
|
50
50
|
if [ -n "$SOUL_LINE" ]; then
|
|
51
|
-
LINES+=("
|
|
51
|
+
LINES+=("Summer project: ${PROJECT_NAME}. GameSoul: ${SOUL_LINE}")
|
|
52
52
|
else
|
|
53
|
-
LINES+=("
|
|
53
|
+
LINES+=("Summer project: ${PROJECT_NAME}.")
|
|
54
54
|
fi
|
|
55
55
|
else
|
|
56
|
-
LINES+=("
|
|
56
|
+
LINES+=("Summer project: ${PROJECT_NAME}.")
|
|
57
57
|
fi
|
|
58
58
|
fi
|
|
59
59
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "summer-engine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "Local Summer CLI and MCP server for Summer Engine. Install and run the engine, connect Claude Code, Cursor, Codex, Gemini, and other agents, and build real games with bundled skills, hooks, and plugins.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"summer-engine",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"files": [
|
|
42
42
|
"dist/",
|
|
43
43
|
"skills/",
|
|
44
|
+
"references/",
|
|
44
45
|
"commands/",
|
|
45
46
|
"hooks/",
|
|
46
47
|
"assets/",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"dev": "tsc --watch",
|
|
66
67
|
"summer": "node dist/bin/summer.js",
|
|
67
68
|
"test": "vitest run",
|
|
69
|
+
"test:public-language": "vitest run src/lib/public-surface-language.test.ts",
|
|
68
70
|
"test:watch": "vitest",
|
|
69
71
|
"prepublishOnly": "npm run build && npm test"
|
|
70
72
|
},
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Collaborative Protocol — "May I write?"
|
|
2
|
+
|
|
3
|
+
> Every Summer skill must follow this. The agent works *with* the user, not around them.
|
|
4
|
+
|
|
5
|
+
## The rule
|
|
6
|
+
|
|
7
|
+
**Before any user-visible write step, the agent must explicitly state what it is about to do and ask permission to proceed.**
|
|
8
|
+
|
|
9
|
+
This applies to:
|
|
10
|
+
- Creating files (`.gd`, `.tscn`, `.tres`, JSON, configs)
|
|
11
|
+
- Modifying existing files (especially `.gd` and `.tscn`)
|
|
12
|
+
- Running irreversible operations (deletion, reset, force-overwrite)
|
|
13
|
+
- Setting up project-wide settings (`project.godot`)
|
|
14
|
+
- Installing tools, libraries, or templates
|
|
15
|
+
|
|
16
|
+
Reading is unconditional. Inspection, scene-tree walks, diagnostics — never need permission.
|
|
17
|
+
|
|
18
|
+
## Phrasing
|
|
19
|
+
|
|
20
|
+
Plain, short, action-first. Examples:
|
|
21
|
+
|
|
22
|
+
> May I create `scenes/player.tscn` and add a CharacterBody3D + Camera3D?
|
|
23
|
+
|
|
24
|
+
> I'm about to overwrite `levels/level_01.tscn`. The current version has 14 nodes — I'll preserve them and add the new lighting setup. Continue?
|
|
25
|
+
|
|
26
|
+
> May I attach `scripts/player_controller.gd` to `./World/Player`?
|
|
27
|
+
|
|
28
|
+
> I'm going to bind `move_forward`, `move_back`, `move_left`, `move_right`, `jump`. OK?
|
|
29
|
+
|
|
30
|
+
## What this prevents
|
|
31
|
+
|
|
32
|
+
1. **Silent overwrites.** The agent stomps the user's hand-edited script.
|
|
33
|
+
2. **Cascading scope creep.** A "small fix" turns into a 30-file refactor.
|
|
34
|
+
3. **Unclear state.** The user has no idea what changed when something breaks.
|
|
35
|
+
4. **Trust loss.** One unauthorized edit and the user stops trusting the agent.
|
|
36
|
+
|
|
37
|
+
## What this is NOT
|
|
38
|
+
|
|
39
|
+
- Not a confirmation dialog for every property change in a single skill execution. Group related writes into one ask: "I'm about to add the player root, attach the controller script, and bind 5 input actions. OK?"
|
|
40
|
+
- Not a request for design input. The skill should know what to do; the ask is for permission, not direction.
|
|
41
|
+
- Not a stop on simple read-only ops or single-property tweaks the user clearly directed.
|
|
42
|
+
|
|
43
|
+
## Linter check
|
|
44
|
+
|
|
45
|
+
The `workflow/skill-test/SKILL.md` static linter looks for the phrases:
|
|
46
|
+
- "May I" / "May I write" / "May I create" / "May I attach"
|
|
47
|
+
- "I'm about to"
|
|
48
|
+
- "Continue?" / "OK?" / "Proceed?"
|
|
49
|
+
|
|
50
|
+
A skill that mutates files but never says any of these fails the linter.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# GDScript Style — Summer Conventions
|
|
2
|
+
|
|
3
|
+
> The bar for GDScript in Summer. Skills should produce code that matches this. Where Godot's official style guide is silent, this is the tiebreaker.
|
|
4
|
+
|
|
5
|
+
## File structure
|
|
6
|
+
|
|
7
|
+
```gdscript
|
|
8
|
+
class_name PlayerController
|
|
9
|
+
extends CharacterBody3D
|
|
10
|
+
|
|
11
|
+
# 1. Constants
|
|
12
|
+
const SPEED := 5.0
|
|
13
|
+
const JUMP_VELOCITY := 4.5
|
|
14
|
+
const GRAVITY := 9.8
|
|
15
|
+
|
|
16
|
+
# 2. Exports (designer-tweakable in inspector)
|
|
17
|
+
@export var move_speed: float = 5.0
|
|
18
|
+
@export var jump_height: float = 1.0
|
|
19
|
+
@export_range(0.1, 10.0) var look_sensitivity: float = 1.0
|
|
20
|
+
|
|
21
|
+
# 3. Signals (events this node emits)
|
|
22
|
+
signal died
|
|
23
|
+
signal health_changed(new_value: int)
|
|
24
|
+
|
|
25
|
+
# 4. Onready references (cached node lookups)
|
|
26
|
+
@onready var camera: Camera3D = $Camera3D
|
|
27
|
+
@onready var collision: CollisionShape3D = $CollisionShape3D
|
|
28
|
+
|
|
29
|
+
# 5. Private state (snake_case, leading underscore optional)
|
|
30
|
+
var _is_grounded: bool = false
|
|
31
|
+
var _velocity := Vector3.ZERO
|
|
32
|
+
|
|
33
|
+
# 6. Lifecycle (in canonical order)
|
|
34
|
+
func _ready() -> void:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
func _process(delta: float) -> void:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
func _physics_process(delta: float) -> void:
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
func _input(event: InputEvent) -> void:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
# 7. Public API (PascalCase or snake_case methods, snake_case for funcs)
|
|
47
|
+
func take_damage(amount: int) -> void:
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
# 8. Private helpers (leading underscore)
|
|
51
|
+
func _calculate_movement(delta: float) -> Vector3:
|
|
52
|
+
return Vector3.ZERO
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Type hints
|
|
56
|
+
|
|
57
|
+
**Always type-hint.** No bare `var x = 5`. Use `:=` for inferred typing or `:` for explicit.
|
|
58
|
+
|
|
59
|
+
```gdscript
|
|
60
|
+
# RIGHT
|
|
61
|
+
var speed: float = 5.0
|
|
62
|
+
var name := "Player"
|
|
63
|
+
func attack(target: Node3D, amount: int) -> bool:
|
|
64
|
+
return true
|
|
65
|
+
|
|
66
|
+
# WRONG
|
|
67
|
+
var speed = 5.0
|
|
68
|
+
func attack(target, amount):
|
|
69
|
+
return true
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Naming
|
|
73
|
+
|
|
74
|
+
| Thing | Convention | Example |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| Class | PascalCase | `class_name PlayerController` |
|
|
77
|
+
| File | snake_case | `player_controller.gd` |
|
|
78
|
+
| Variable, function | snake_case | `move_speed`, `take_damage()` |
|
|
79
|
+
| Constant | SCREAMING_SNAKE_CASE | `const MAX_HEALTH := 100` |
|
|
80
|
+
| Signal | snake_case (past tense for events) | `died`, `health_changed` |
|
|
81
|
+
| Private | leading underscore | `_is_grounded`, `_calculate_movement` |
|
|
82
|
+
| Node in scene | PascalCase | `Player`, `Camera3D`, `CollisionShape3D` |
|
|
83
|
+
|
|
84
|
+
## Signals
|
|
85
|
+
|
|
86
|
+
Define with typed args. Connect in `_ready()` or in scene `.tscn` directly.
|
|
87
|
+
|
|
88
|
+
```gdscript
|
|
89
|
+
signal health_changed(new_value: int, max_value: int)
|
|
90
|
+
|
|
91
|
+
func _ready() -> void:
|
|
92
|
+
health_changed.connect(_on_health_changed)
|
|
93
|
+
|
|
94
|
+
func _on_health_changed(new_value: int, max_value: int) -> void:
|
|
95
|
+
pass
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Tweens
|
|
99
|
+
|
|
100
|
+
Use `create_tween()` for animation. Don't manually lerp in `_process` unless you need fine control.
|
|
101
|
+
|
|
102
|
+
```gdscript
|
|
103
|
+
var tween := create_tween()
|
|
104
|
+
tween.tween_property(self, "modulate", Color.WHITE, 0.3)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## What to avoid
|
|
108
|
+
|
|
109
|
+
- Bare `var x = something` (no type)
|
|
110
|
+
- `Object` typed parameters (use specific class)
|
|
111
|
+
- `match` for two-branch logic (use `if`)
|
|
112
|
+
- Recreating node lookups in `_process` (cache via `@onready`)
|
|
113
|
+
- Hard-coded strings for node paths in code (use `@onready` + scene-relative paths)
|
|
114
|
+
- Setting `position` in `_process` for physics objects (use `_physics_process` and `velocity`)
|
|
115
|
+
|
|
116
|
+
## See also
|
|
117
|
+
|
|
118
|
+
- [Official Godot GDScript style guide](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html)
|
|
119
|
+
- `scripting-patterns/gdscript-patterns/SKILL.md` — patterns and idioms
|
|
120
|
+
- `scripting-patterns/signal-patterns/SKILL.md` — signal usage
|
|
121
|
+
- `scripting-patterns/state-machine-patterns/SKILL.md` — state machine patterns
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Summer Engine Compatibility Reference
|
|
2
|
+
|
|
3
|
+
> Read this before writing version-sensitive code, especially shaders,
|
|
4
|
+
> rendering code, extensions, or export configuration.
|
|
5
|
+
|
|
6
|
+
## Current technical base
|
|
7
|
+
|
|
8
|
+
Summer Engine is the product. Its current upstream technical base is **4.6.1**
|
|
9
|
+
(stable, Mono), the approved next target is **4.7.1**, and Summer follows
|
|
10
|
+
upstream continuously. These are compatibility and lineage facts. They are not
|
|
11
|
+
the Summer product name or a permanent SDK version.
|
|
12
|
+
|
|
13
|
+
The repository source of truth is
|
|
14
|
+
`compatibility/summer-engine.json`. The running engine also reports its measured
|
|
15
|
+
technical version:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
<engineBinaryPath> --version # measured: 4.6.1.stable.mono.custom_build.b708b1182
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Get `engineBinaryPath` from `summer_get_project_context`. Prefer live
|
|
22
|
+
inspection to a copied version string. Creator onboarding and headlines should
|
|
23
|
+
say Summer Engine, Summer game, Summer SDK, and GDScript. Use the upstream name
|
|
24
|
+
only where technical compatibility, migration, extension APIs, contribution
|
|
25
|
+
routing, attribution, or licensing requires it.
|
|
26
|
+
|
|
27
|
+
## LLM training cutoff versus upstream releases
|
|
28
|
+
|
|
29
|
+
| Domain | Godot 4.x churn | Action |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| Scripting (GDScript core) | low | Trust your training. Spot-check signatures only when something feels off. |
|
|
32
|
+
| Scene / node tree APIs | low | Trust your training. |
|
|
33
|
+
| Renderer (`RenderingServer`, `Compositor`) | high in 4.4 / 4.5 | Verify before writing. Check `MovieMaker`, `Compositor` effects, `RenderSceneBuffers` — these renamed/added recently. |
|
|
34
|
+
| Shaders (`canvas_item`, `spatial`, `compute`) | medium | Built-in functions stable, but `hint_*` flags shifted. Verify `hint_screen_texture` / `hint_depth_texture` syntax. |
|
|
35
|
+
| Animation (`AnimationTree`, `AnimationMixer`) | high (4.0 → 4.3 rename) | Use `AnimationMixer` for new code, not deprecated `AnimationPlayer`-as-mixer. |
|
|
36
|
+
| Multiplayer (`MultiplayerAPI`) | medium | High-level API stable. `SceneReplicationConfig` settled in 4.0+. |
|
|
37
|
+
| Editor / EditorPlugin | medium | Spot-check. |
|
|
38
|
+
| `Tween` / `SceneTreeTween` | low | Stable since 4.0. |
|
|
39
|
+
|
|
40
|
+
## Summer-specific deltas from the upstream engine
|
|
41
|
+
|
|
42
|
+
- Local API server runs on `localhost:6550` (set per machine via `~/.summer/api-token`).
|
|
43
|
+
- Engine ships a webview module in `modules/1summer_engine/`. Do not assume the
|
|
44
|
+
unmodified upstream editor for UI patches.
|
|
45
|
+
- Project root contains `.summer/` for project memory; do not delete it.
|
|
46
|
+
|
|
47
|
+
## When in doubt
|
|
48
|
+
|
|
49
|
+
1. Use Summer MCP tools (`summer_inspect_node`, `summer_inspect_resource`) to read live editor state instead of guessing.
|
|
50
|
+
2. Use `summer_get_diagnostics` after every scene change.
|
|
51
|
+
3. Check `references/mcp-tools-reference.md` for the canonical tool list.
|