gdharness 1.3.3 → 1.3.4
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/build/cli.js +105 -74
- package/build/godot/addons/gdharness_editor/animation_reads.gd +3 -2
- package/build/godot/addons/gdharness_editor/declared_values.gd +157 -4
- package/build/godot/addons/gdharness_editor/file_reads.gd +15 -3
- package/build/godot/addons/gdharness_editor/headless_check.gd +44 -23
- package/build/godot/addons/gdharness_editor/property_paths.gd +225 -0
- package/build/godot/addons/gdharness_editor/property_paths.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/property_values.gd +195 -221
- package/build/godot/addons/gdharness_editor/reading.gd +15 -0
- package/build/godot/addons/gdharness_editor/same_values.gd +177 -0
- package/build/godot/addons/gdharness_editor/same_values.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/scene_file.gd +97 -14
- package/build/godot/addons/gdharness_editor/serialisation.gd +75 -3
- package/build/godot/addons/gdharness_editor/tool_executor.gd +9 -3
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +38 -35
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +3 -2
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +91 -0
- package/build/godot/addons/gdharness_editor/tools/scene_groups.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +68 -2
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +94 -333
- package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +363 -0
- package/build/godot/addons/gdharness_editor/tools/signal_tools.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/reading.gd +15 -0
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +10 -26
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +3 -2
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +2 -1
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +30 -0
- package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -3
- package/build/godot/operations/animation_reads.gd +3 -2
- package/build/godot/operations/declared_values.gd +157 -4
- package/build/godot/operations/dependencies.gd +14 -39
- package/build/godot/operations/editor_tools.gd +4 -3
- package/build/godot/operations/file_reads.gd +15 -3
- package/build/godot/operations/gdscript_analysis.gd +229 -75
- package/build/godot/operations/gdscript_authoring.gd +142 -34
- package/build/godot/operations/import_pipeline.gd +17 -6
- package/build/godot/operations/logger.gd +7 -0
- package/build/godot/operations/property_paths.gd +225 -0
- package/build/godot/operations/property_values.gd +195 -221
- package/build/godot/operations/reading.gd +15 -0
- package/build/godot/operations/same_values.gd +177 -0
- package/build/godot/operations/serialisation.gd +75 -3
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -9222,6 +9222,19 @@ function withNotCompiled(note, entries) {
|
|
|
9222
9222
|
const path = entries.map(notCompiledIn).find((found) => found !== undefined);
|
|
9223
9223
|
return path === undefined ? note : `${note} ${path} did not compile, so every run of this project starts its autoloads without it until it is fixed; its errors are among these.`;
|
|
9224
9224
|
}
|
|
9225
|
+
function withoutAsides(entries) {
|
|
9226
|
+
const kept = [];
|
|
9227
|
+
let aside = false;
|
|
9228
|
+
for (const entry of entries) {
|
|
9229
|
+
const mark = entry.source === "stderr" ? entry.text : "";
|
|
9230
|
+
if (mark === ASIDE || mark === RESUMED) {
|
|
9231
|
+
aside = mark === ASIDE;
|
|
9232
|
+
} else if (!aside) {
|
|
9233
|
+
kept.push(entry);
|
|
9234
|
+
}
|
|
9235
|
+
}
|
|
9236
|
+
return kept;
|
|
9237
|
+
}
|
|
9225
9238
|
function problemsIn(log) {
|
|
9226
9239
|
return problemsAmong(log.everything());
|
|
9227
9240
|
}
|
|
@@ -9368,7 +9381,7 @@ async function runOperation(engine, operation, params, projectPath) {
|
|
|
9368
9381
|
} finally {
|
|
9369
9382
|
discard(paramsDir);
|
|
9370
9383
|
}
|
|
9371
|
-
const everything = ran.log.everything();
|
|
9384
|
+
const everything = withoutAsides(ran.log.everything());
|
|
9372
9385
|
const marked = (text) => everything.findIndex((entry) => entry.source === "stderr" && entry.text === text);
|
|
9373
9386
|
const answered = marked(ANSWERED);
|
|
9374
9387
|
const waiting = marked(WAITING);
|
|
@@ -9452,7 +9465,7 @@ function answerIn(file) {
|
|
|
9452
9465
|
};
|
|
9453
9466
|
}
|
|
9454
9467
|
}
|
|
9455
|
-
var AFTER_ANSWER_NOTE = "Printed after this operation had written its answer, while the engine ran the project's autoloads and shut down: Godot starts a project's autoloads in every script run and cannot be told not to. An error raised in a project script here is that autoload's own, and none of these changes the answer.", BEFORE_OPERATION_NOTE = "Printed while the engine started the project's autoloads, before this operation ran: an operation that compiles the project's scripts waits for them, because the engine knows an autoload's name only once it is in the tree. An error raised in a project script here is that autoload's own.", OWN_ERROR = "[ERROR] ", ANSWERED = "[gdharness] answered", WAITING = "[gdharness] waiting for the autoloads", BEGUN = "[gdharness] begun", MESSAGES_KEPT = 200, ERRORS_NAMED = 3;
|
|
9468
|
+
var AFTER_ANSWER_NOTE = "Printed after this operation had written its answer, while the engine ran the project's autoloads and shut down: Godot starts a project's autoloads in every script run and cannot be told not to. An error raised in a project script here is that autoload's own, and none of these changes the answer.", BEFORE_OPERATION_NOTE = "Printed while the engine started the project's autoloads, before this operation ran: an operation that compiles the project's scripts waits for them, because the engine knows an autoload's name only once it is in the tree. An error raised in a project script here is that autoload's own.", OWN_ERROR = "[ERROR] ", ANSWERED = "[gdharness] answered", WAITING = "[gdharness] waiting for the autoloads", BEGUN = "[gdharness] begun", ASIDE = "[gdharness] aside", RESUMED = "[gdharness] resumed", MESSAGES_KEPT = 200, ERRORS_NAMED = 3;
|
|
9456
9469
|
var init_headless = __esm(() => {
|
|
9457
9470
|
init_doc_cache();
|
|
9458
9471
|
init_engine_run();
|
|
@@ -11942,7 +11955,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
11942
11955
|
};
|
|
11943
11956
|
PROPERTIES = {
|
|
11944
11957
|
type: "object",
|
|
11945
|
-
description: `Properties to set, keyed by Godot property name. Vectors, colours and the like may be written as {"x": 1, "y": 2} or tagged {"_type": "Vector2", "x": 1, "y": 2}, which is the form a read answers with, so a value read off one node can be written straight to another. One carrying a field its type has not, such as a z for a Vector2, is refused naming it. A colour may also be given as its html code, "#ff8000" or "#ff800080". A key may also be a colon path into one of the components of a vector, a colour, a rectangle or a transform, as GDScript names them, so one axis is written alone: "position:x", "modulate:a", "region_rect:size:y"; a component the value does not have is refused, naming the ones it has. A property holding a node takes the path to it from the node being set, such as "../Player". Each value is read back once set, and one the engine changed or refused is refused with what it holds. An enum property takes the name of a value
|
|
11958
|
+
description: `Properties to set, keyed by Godot property name. Vectors, colours and the like may be written as {"x": 1, "y": 2} or tagged {"_type": "Vector2", "x": 1, "y": 2}, which is the form a read answers with, so a value read off one node can be written straight to another. One carrying a field its type has not, such as a z for a Vector2, is refused naming it. A colour may also be given as its html code, "#ff8000" or "#ff800080". A key may also be a colon path into one of the components of a vector, a colour, a rectangle or a transform, as GDScript names them, so one axis is written alone: "position:x", "modulate:a", "region_rect:size:y"; a component the value does not have is refused, naming the ones it has. A property holding a node takes the path to it from the node being set, such as "../Player". A property holding a Resource takes the res:// path of a file, which a read answers with its class and, when its script declares one, scriptClass, or a resource built into the scene as {"_type": "CircleShape2D", "radius": 8}, its class (an engine class or a script's class_name) beside its properties. A typed list or map of resources or nodes, such as Array[Item], takes each in the same forms, a node by its path; a read answers a resource built into the scene in that form, with what it holds away from the defaults, so it too can be written to another node. script takes the res:// path of a script to attach, one with no class_name included, and is attached before the rest are set, so the properties it declares can be given beside it. Each value is read back once set, and one the engine changed or refused is refused with what it holds. An enum property takes its number or the name of a value: as the script spells it, as the inspector shows it, or for an engine enum as the class's constant, so Add or BLEND_MODE_ADD; a value past an export range, or a number no value of an enum has, is written as given and named under outsideDeclared. A key may reach into a resource built into this one: the property holding it, a slash, then one of its own, so a TileSet's first atlas source takes "sources/0/0:0/0/probability". A resource kept in a file of its own, or built into the scene an instance comes from, is written in that file, or replaced here by one of this file's own. The next element of a list is made by writing to it, as the inspector's Add Element makes it: physics_layer_0/collision_layer on a TileSet with no physics layer makes its first, and "sources/0/0:0/0/physics_layer_0/polygon_0/points" a tile's first collision polygon on that layer. ${WHOLE_NUMBERS}`,
|
|
11946
11959
|
additionalProperties: true
|
|
11947
11960
|
};
|
|
11948
11961
|
XY = {
|
|
@@ -12252,7 +12265,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12252
12265
|
direction: {
|
|
12253
12266
|
type: "string",
|
|
12254
12267
|
enum: ["forward", "reverse"],
|
|
12255
|
-
description: "forward: what this resource loads, with cycles reported, a script's dependencies including every script whose class_name it uses, marked by_class with the name. summary.total_dependencies counts each file once however many places load it
|
|
12268
|
+
description: "forward: what this resource loads, with cycles reported, a script's dependencies including every script whose class_name it uses, marked by_class with the name. summary.total_resources is the file asked about, so 1; total_dependencies counts each file reached, directly or through another, once however many places load it; total_references counts the entries in the tree, and missing names every file referenced that does not exist, with the files referring to it. reverse: every file that refers to it and how, for a file that is gone as well while anything still refers to it, answered with exists: false (a missing file nothing refers to is refused, naming the nearest files), a scene instancing it, a script extending, preloading or loading it, and for a script with a class_name every use of that name. Each reference carries a kind: ext_resource, extends, preload, load or path for a reference by path; setting, plugin, export_preset and import for one in project.godot, a plugin.cfg, export_presets.cfg or an import sidecar; class_name for a use of the declared name, the declaration itself being the script asked about. Two kinds are mentions rather than uses: doc is a name inside a ## documentation comment, which renaming would break in the generated docs, and comment is one in ordinary prose, which it would only make stale. summary.in_code is the count with both of those left out, which is the number to read when the question is whether anything still uses this. Default forward."
|
|
12256
12269
|
},
|
|
12257
12270
|
depth: { type: "number", description: "forward: how many levels to follow. Default unlimited." },
|
|
12258
12271
|
includeBuiltin: {
|
|
@@ -12282,7 +12295,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12282
12295
|
options: {
|
|
12283
12296
|
type: "object",
|
|
12284
12297
|
ops: ["set_options"],
|
|
12285
|
-
description: `set_options: import options keyed as the .import file spells them, {"compress/mode": 1}. A dictionary option whose keys are numbers, a font's opentype_features or any option already holding number keys, takes them written as strings of digits, and opentype_features also takes an OpenType tag by its four-letter name: {"opentype_features": {"liga": 0}} turns ligatures off. Both are written as the numbers the engine reads.`,
|
|
12298
|
+
description: `set_options: import options keyed as the .import file spells them, {"compress/mode": 1}. A dictionary option whose keys are numbers, a font's opentype_features or any option already holding number keys, takes them written as strings of digits, and opentype_features also takes an OpenType tag by its four-letter name: {"opentype_features": {"liga": 0}} turns ligatures off. Both are written as the numbers the engine reads. One already holding the value given is answered under unchanged_options rather than updated_options, and when none changed nothing is written or reimported.`,
|
|
12286
12299
|
additionalProperties: true
|
|
12287
12300
|
},
|
|
12288
12301
|
reimport: {
|
|
@@ -12457,7 +12470,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12457
12470
|
name: "scene_tree",
|
|
12458
12471
|
title: "Scene tree",
|
|
12459
12472
|
effect: "read",
|
|
12460
|
-
description: "The nodes of a scene file: names, classes and hierarchy, with properties when asked. A node that instances another scene names that file under instanceOf, and the nodes listed under it come from that file rather than this one; its editableChildren says whether this scene, or a scene it inherits, keeps values of its own for them (scene_node set editableChildren). Needs no editor: one serving the project answers and says whether it holds unsaved changes to the scene, and with none a headless engine reads the file without making its nodes, so no script of theirs runs (autoloads still start once it has answered, as in every headless call). For the nodes of a game that is running, runtime_inspect tree.",
|
|
12473
|
+
description: "The nodes of a scene file: names, classes and hierarchy, with properties when asked. A node that instances another scene names that file under instanceOf, and the nodes listed under it come from that file rather than this one; its editableChildren says whether this scene, or a scene it inherits, keeps values of its own for them (scene_node set editableChildren). A node in any group answers groups, sorted, from this file and every scene it comes from. Needs no editor: one serving the project answers and says whether it holds unsaved changes to the scene, and with none a headless engine reads the file without making its nodes, so no script of theirs runs (autoloads still start once it has answered, as in every headless call). For the nodes of a game that is running, runtime_inspect tree.",
|
|
12461
12474
|
parameters: {
|
|
12462
12475
|
projectPath: PROJECT_PATH,
|
|
12463
12476
|
scenePath: SCENE_PATH,
|
|
@@ -12472,7 +12485,8 @@ var init_tool_definitions = __esm(() => {
|
|
|
12472
12485
|
{
|
|
12473
12486
|
name: "scene_node",
|
|
12474
12487
|
title: "Scene nodes",
|
|
12475
|
-
description: `One node in a scene file: add, read, set, duplicate, reparent or delete it, or paint TileMap cells. Any ClassDB node type or script class can be added, so a NavigationRegion2D, an AnimationTree or a Camera3D is an add with that nodeType and its properties, and another scene is instanced by an add with instancePath. A set with properties {"name": "Boss"} renames a node, and answers nodePath as its new path. A rename or a reparent carries the node paths naming the node, as the editor's rename does: NodePath values on nodes (in arrays, dictionaries, built-in resources, %unique paths) and the tracks its players' animations hold, saving a library kept in a .tres of its own
|
|
12488
|
+
description: `One node in a scene file: add, read, set, duplicate, reparent or delete it, or paint TileMap cells. Any ClassDB node type or script class can be added, so a NavigationRegion2D, an AnimationTree or a Camera3D is an add with that nodeType and its properties, and another scene is instanced by an add with instancePath. A set with properties {"name": "Boss"} renames a node, and answers nodePath as its new path. A rename or a reparent carries the node paths naming the node, as the editor's rename does: NodePath values on nodes (in arrays, dictionaries, built-in resources, %unique paths) and the tracks its players' animations hold, saving a library kept in a .tres of its own, and answers each rewrite under retargeted and each path it left under notRetargeted. The move is followed into every other .tscn that instances or inherits this scene at any depth: the editable children, values, added nodes and connections named by the old path are rewritten, since Godot finds a moved node's values by unique_id but editable children only by path and drops the values kept below them on the next save, and that scene's node paths and tracks are carried as above. A delete rewrites no path, and answers under stillNaming what named the deleted node and now names nothing. A property holding a Resource takes the res:// path of one, so a texture, a material or a theme is a set like any other. A write is refused while the editor holds unsaved changes to the scene. A node this scene inherits takes values of this scene's own, and so does a node inside an instance of another scene once that instance's editableChildren is true; neither can be moved, renamed, copied or deleted, since the other scene makes it again on load. ${WITHOUT_AN_EDITOR}`,
|
|
12489
|
+
answer: "get answers nodeType, the node's engine class, with scriptClass when its script declares a class_name; nodePath, its path from the root however it was named; setHere, the properties this scene's own file sets on it; and valuesFrom, the scene every other value comes from, when another scene makes the node. retargeted lists each path a rename or a reparent rewrote, as {scenePath, nodePath, property or animation and track, from, to}, and notRetargeted each it left, with a reason: a track kept in another scene or an imported file, or a value another scene gives that the move left naming nothing. followed names the other scenes a move rewrote, and notFollowed any left as they were, with why. stillNaming lists each node path and track, here and in the scenes instancing or inheriting this one, that named a deleted node, and deletedWithIt each node of this scene's own that went with it, the nodes inside an instance going with the instance. groups lists, sorted, every group a node is in, on a get, an add that gave addGroups and every set that changes them; get adds groupsHere, the groups this file puts it in, when another scene puts it in others. Each of these lists is answered only when it names anything. alsoChanged gives the other properties the engine changed in step with a set, as a Control's offsets with its size, and those a reparent changed to keep the node where it is drawn, as {was, now}.",
|
|
12476
12490
|
parameters: {
|
|
12477
12491
|
projectPath: PROJECT_PATH,
|
|
12478
12492
|
scenePath: SCENE_PATH,
|
|
@@ -12499,17 +12513,34 @@ var init_tool_definitions = __esm(() => {
|
|
|
12499
12513
|
ops: ["set"],
|
|
12500
12514
|
description: "set: on an instance of another scene, whether its children are editable here, as the editor's Editable Children makes them. True lets scene_node set give the nodes inside that instance values of this scene's own, which no other instance shares. An instance nested inside another takes it once the one around it has editable children. False drops every value this scene keeps for them, and every node it added below one of them. The answer names the nodes whose values went under droppedValues (they stay, with the instance's own values) and the added nodes that went under droppedNodes; a node added straight under the instance stays. The answer says editableChildren as the file now holds it."
|
|
12501
12515
|
},
|
|
12516
|
+
addGroups: {
|
|
12517
|
+
type: "array",
|
|
12518
|
+
items: { type: "string" },
|
|
12519
|
+
ops: ["add", "set"],
|
|
12520
|
+
description: "add and set: groups to put the node in, saved in this scene's file as the editor's Groups dock saves them. One it is in already is kept as it is."
|
|
12521
|
+
},
|
|
12522
|
+
removeGroups: {
|
|
12523
|
+
type: "array",
|
|
12524
|
+
items: { type: "string" },
|
|
12525
|
+
ops: ["set"],
|
|
12526
|
+
description: "set: groups to take the node out of. One it is not in is refused, and so is one another scene puts it in (the scene that makes it, instances it or is inherited here), which only that scene can take it out of."
|
|
12527
|
+
},
|
|
12502
12528
|
newName: { type: "string", ops: ["duplicate"], description: "duplicate: the copy's name." },
|
|
12503
12529
|
newParentPath: {
|
|
12504
12530
|
type: "string",
|
|
12505
12531
|
ops: ["reparent"],
|
|
12506
|
-
description: "reparent: the new parent, which may be the one it has, to move it among its siblings."
|
|
12532
|
+
description: "reparent: the new parent, which may be the one it has, to move it among its siblings. In the scenes the move is followed into, the parent_id_path, from_uid_path and to_uid_path saved beside each rewritten path are dropped, since their ids ran through the old parent; the node's own unique_id is kept, and the next save writes the dropped ones again."
|
|
12533
|
+
},
|
|
12534
|
+
keepGlobalTransform: {
|
|
12535
|
+
type: "boolean",
|
|
12536
|
+
ops: ["reparent"],
|
|
12537
|
+
description: "reparent: whether the node stays where it is drawn, its transform worked out again under the new parent, as the editor's reparent and Node.reparent keep it. A Control keeps its position only. Default true; false keeps its own transform, so it moves with the new parent."
|
|
12507
12538
|
},
|
|
12508
12539
|
index: {
|
|
12509
12540
|
type: "integer",
|
|
12510
12541
|
minimum: 0,
|
|
12511
|
-
ops: ["add", "reparent"],
|
|
12512
|
-
description: "add and reparent: where the node goes among the parent's children, 0 for first. Default last. Child order is draw order in a CanvasItem and layout order in a Container."
|
|
12542
|
+
ops: ["add", "duplicate", "reparent"],
|
|
12543
|
+
description: "add, duplicate and reparent: where the node goes among the parent's children, 0 for first. Default last, except for a copy under the original's own parent, which goes right after it. Child order is draw order in a CanvasItem and layout order in a Container."
|
|
12513
12544
|
},
|
|
12514
12545
|
includeDefaults: {
|
|
12515
12546
|
type: "boolean",
|
|
@@ -12532,22 +12563,22 @@ var init_tool_definitions = __esm(() => {
|
|
|
12532
12563
|
},
|
|
12533
12564
|
get: {
|
|
12534
12565
|
effect: "read",
|
|
12535
|
-
summary: "read a node's properties, and a TileMapLayer's or TileMap's cells as set_tilemap_cells takes them, the first 1000 with cellCount for all. An instance of another scene also answers instanceOf and editableChildren, as scene_tree does",
|
|
12566
|
+
summary: "read a node's class, path, properties and where its values come from, and a TileMapLayer's or TileMap's cells as set_tilemap_cells takes them, the first 1000 with cellCount for all. An instance of another scene also answers instanceOf and editableChildren, as scene_tree does",
|
|
12536
12567
|
requires: ["nodePath"]
|
|
12537
12568
|
},
|
|
12538
12569
|
set: {
|
|
12539
12570
|
effect: "destructive",
|
|
12540
|
-
summary: "set properties on a node,
|
|
12571
|
+
summary: "set properties on a node, make the children of an instance editable, or put it in groups or take it out of them; give any of them together",
|
|
12541
12572
|
requires: ["nodePath"]
|
|
12542
12573
|
},
|
|
12543
12574
|
duplicate: {
|
|
12544
12575
|
effect: "additive",
|
|
12545
|
-
summary: "copy a node and its children,
|
|
12576
|
+
summary: "copy a node and its children, right after it or under parentNodePath, answering the copy's newNodePath, parentNodePath and index",
|
|
12546
12577
|
requires: ["nodePath", "newName"]
|
|
12547
12578
|
},
|
|
12548
12579
|
reparent: {
|
|
12549
12580
|
effect: "destructive",
|
|
12550
|
-
summary: "move a node under another parent, or to another place among its siblings",
|
|
12581
|
+
summary: "move a node under another parent, keeping where it is drawn, or to another place among its siblings",
|
|
12551
12582
|
requires: ["nodePath", "newParentPath"]
|
|
12552
12583
|
},
|
|
12553
12584
|
delete: { effect: "destructive", summary: "remove a node and its children", requires: ["nodePath"] },
|
|
@@ -12561,7 +12592,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12561
12592
|
{
|
|
12562
12593
|
name: "scene_signal",
|
|
12563
12594
|
title: "Scene signals",
|
|
12564
|
-
description: `Signal connections in a scene file. Each connection answers with its flags as the number and as flagNames; persist is on every connection, since a scene saves no other kind. A connect of a pair already connected says alreadyConnected, with flagsBefore when it changed the flags. A connect to a method the target does not have is still written, as the editor's own dialog allows, since the method may be written next; methodFound false says so, and until the method exists the signal fails each time it is emitted. list marks editable false on a connection an instanced scene makes inside itself, which only that scene can change. ${WITHOUT_AN_EDITOR}`,
|
|
12595
|
+
description: `Signal connections in a scene file. Each connection answers with its flags as the number and as flagNames; persist is on every connection, since a scene saves no other kind. A connect of a pair already connected says alreadyConnected, with flagsBefore when it changed the flags. A connect to a method the target does not have is still written, as the editor's own dialog allows, since the method may be written next; methodFound false says so, and until the method exists the signal fails each time it is emitted. One whose method cannot take what the signal passes, with its binds and unbinds (too few or too many arguments, an object where the method takes a value or the reverse, or an engine class unrelated to the one it takes), is written too, and answers argumentsFit false with misfit saying why; list gives each connection its methodFound, and misfit when it has one. list marks editable false on a connection an instanced scene makes inside itself, which only that scene can change. ${WITHOUT_AN_EDITOR}`,
|
|
12565
12596
|
parameters: {
|
|
12566
12597
|
projectPath: PROJECT_PATH,
|
|
12567
12598
|
scenePath: SCENE_PATH,
|
|
@@ -12618,7 +12649,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12618
12649
|
animationName: {
|
|
12619
12650
|
type: "string",
|
|
12620
12651
|
ops: ["read", "create", "add_track", "set", "rename", "remove", "add_state"],
|
|
12621
|
-
description: "The animation in the player. read: the one to answer with whole, its tracks a list; without it, read lists them, each with the number of its tracks under tracks. add_state: the one that state plays."
|
|
12652
|
+
description: "The animation in the player. read: the one to answer with whole, its tracks a list; without it, read lists them, each with the number of its tracks under tracks. add_state: the one that state plays. One the player does not have yet is written all the same, answering animationFound false and why under animationMissing."
|
|
12622
12653
|
},
|
|
12623
12654
|
newName: {
|
|
12624
12655
|
type: "string",
|
|
@@ -12743,7 +12774,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12743
12774
|
extends: {
|
|
12744
12775
|
type: "string",
|
|
12745
12776
|
ops: ["create"],
|
|
12746
|
-
description: "create: the base class. Default Node. Not with content."
|
|
12777
|
+
description: "create: the base class. Default the class the template is written for, or Node with no template. Not with content."
|
|
12747
12778
|
},
|
|
12748
12779
|
content: {
|
|
12749
12780
|
type: "string",
|
|
@@ -12754,13 +12785,13 @@ var init_tool_definitions = __esm(() => {
|
|
|
12754
12785
|
type: "string",
|
|
12755
12786
|
enum: ["singleton", "state_machine", "component", "resource"],
|
|
12756
12787
|
ops: ["create"],
|
|
12757
|
-
description: "create: a starting shape."
|
|
12788
|
+
description: "create: a starting shape. resource is written for a Resource and the others for a Node; an extends outside that class is refused."
|
|
12758
12789
|
},
|
|
12759
12790
|
modifications: { ...SCRIPT_MODIFICATIONS, ops: ["modify"] },
|
|
12760
12791
|
symbol: {
|
|
12761
12792
|
type: "string",
|
|
12762
12793
|
ops: ["rename"],
|
|
12763
|
-
description: "rename: what to rename, declared by the script at scriptPath: its class_name, or a method, variable, constant, signal, enum, enum value or inner class at its top level. A
|
|
12794
|
+
description: "rename: what to rename, declared by the script at scriptPath: its class_name, or a method, variable, constant, signal, enum, enum value or inner class at its top level. A class_name is renamed from the files and needs no editor: every bare use in code, the declaration, doc links such as [Told] and [method Told.say], and the script_class a .tres records. A script that declares something of its own by the old name, and a use after a dot, are left alone, since which of those mean the class cannot be told from the text. Everything else, an inner class and an enum value included, is renamed from what the editor's language server resolves to it, so it needs the editor open on this project; a method is renamed together with every override of it in the classes inheriting it, and from the topmost class declaring it when scriptPath's is itself an override. Doc links naming the member through any class inheriting it are renamed too, and so are a scene's or resource's saved value of a variable on a node or resource whose script inherits it, and a connection naming the signal on its emitter or the method on its receiver. A name the engine itself declares on the native base, such as _ready, is refused, as is a new name already taken: by a class, an autoload, an identifier in code, a native class or built-in type, or a member anywhere in the class's chain."
|
|
12764
12795
|
},
|
|
12765
12796
|
newName: { type: "string", ops: ["rename"], description: "rename: the new name." },
|
|
12766
12797
|
newScriptPath: {
|
|
@@ -12814,7 +12845,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12814
12845
|
operations: {
|
|
12815
12846
|
structure: {
|
|
12816
12847
|
effect: "read",
|
|
12817
|
-
summary: "functions, variables, signals, constants, enums, inner_classes, class_name, extends and line_count, read from the file, and dependencies: the paths it loads or preloads as written, then the scripts declaring each project class_name its code uses, which classes_used names with the class; autoloads_used names each autoload the code uses by its global name, with the autoload's script, which the project loads rather than this script, so it is not under dependencies",
|
|
12848
|
+
summary: "functions, variables (static ones marked is_static; one written with := has the type of a literal or built-in constructor it is given, marked inferred, as a constant always does), signals, constants, enums, inner_classes (each with its name, line and extends, and its own members in these same fields), class_name, extends and line_count, read from the file, and dependencies: the paths it loads or preloads as written, then the scripts declaring each project class_name its code uses, which classes_used names with the class; autoloads_used names each autoload the code uses by its global name, with the autoload's script, which the project loads rather than this script, so it is not under dependencies",
|
|
12818
12849
|
requires: []
|
|
12819
12850
|
},
|
|
12820
12851
|
symbols: {
|
|
@@ -12835,7 +12866,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12835
12866
|
name: "script_diagnostics",
|
|
12836
12867
|
title: "Script diagnostics",
|
|
12837
12868
|
effect: "read",
|
|
12838
|
-
description: "Errors and warnings for a script, or for several, from the editor's language server, and whether each is clean. With no editor of this project open, so no language server of it to ask, a short headless engine compiles the scripts instead and the answer says checkedBy: engine: every error that stops a script compiling, with its line and no column, dependenciesWithErrors naming the other scripts that failed while it loaded, typesMissingFromTheClassCache naming a class the project declares that the engine could not resolve because the class cache lacks it, with staleAnalysis saying what rewrites the cache, and warnings null, since the engine reports warnings only to an editor. Each diagnostic carries its severity (error or warning), its message, and where it is as the editor shows it: line and column counted from 1, and endLine and endColumn just past its end. Diagnostics are checked against the project's own files, and the two that the files disprove are named rather than passed on: a member the class cache's file declares, or a project class it extends does, a method, property, constant, static function or enum member, comes back under contradictedByTheFile with the script declaring it, and so does one a diagnostic names alone as an external class member, read against the class it is looked up on in the line it is on; and a class this project declares that the diagnostic could not resolve comes back under typesTheEditorHasNotLoaded, with inTheClassCache saying whether a launched game would resolve it. staleAnalysis then says what to do, and for both states it is editor_rescan first: it asks the editor already running, starts nothing, and has cleared each in every reproduction measured. Two exceptions are named when they apply. For an enum member, constant or static function of a global class the reload comes first: in the one project that has reproduced a stale enum member, editor_rescan with reloadScript on the declaring script cleared it and a plain rescan did not. And an editor whose last scan wrote the class cache shorter than the file holds a list behind the files and writes it on every scan, so on that editor the rescan loads nothing and staleAnalysis says editor_launch restart instead. What follows differs: for a stale analysed type, editor_rescan with reloadScript recompiles the held copy and editor_launch restart is the last resort that costs a window; for a class missing from the cache, project_import refresh_classes rewrites the cache from disk at the cost of a short headless engine, which matters beside a running bench.",
|
|
12869
|
+
description: "Errors and warnings for a script, or for several, from the editor's language server, and whether each is clean. With no editor of this project open, so no language server of it to ask, a short headless engine compiles the scripts instead and the answer says checkedBy: engine: every error that stops a script compiling, with its line and no column (a call to a method another class lacks is not one, since GDScript checks those only on self: the object may be a subclass that has it, so it fails at run time instead), dependenciesWithErrors naming the other scripts that failed while it loaded, typesMissingFromTheClassCache naming a class the project declares that the engine could not resolve because the class cache lacks it, with staleAnalysis saying what rewrites the cache, and warnings null, since the engine reports warnings only to an editor. Each diagnostic carries its severity (error or warning), its message, and where it is as the editor shows it: line and column counted from 1, and endLine and endColumn just past its end. Diagnostics are checked against the project's own files, and the two that the files disprove are named rather than passed on: a member the class cache's file declares, or a project class it extends does, a method, property, constant, static function or enum member, comes back under contradictedByTheFile with the script declaring it, and so does one a diagnostic names alone as an external class member, read against the class it is looked up on in the line it is on; and a class this project declares that the diagnostic could not resolve comes back under typesTheEditorHasNotLoaded, with inTheClassCache saying whether a launched game would resolve it. staleAnalysis then says what to do, and for both states it is editor_rescan first: it asks the editor already running, starts nothing, and has cleared each in every reproduction measured. Two exceptions are named when they apply. For an enum member, constant or static function of a global class the reload comes first: in the one project that has reproduced a stale enum member, editor_rescan with reloadScript on the declaring script cleared it and a plain rescan did not. And an editor whose last scan wrote the class cache shorter than the file holds a list behind the files and writes it on every scan, so on that editor the rescan loads nothing and staleAnalysis says editor_launch restart instead. What follows differs: for a stale analysed type, editor_rescan with reloadScript recompiles the held copy and editor_launch restart is the last resort that costs a window; for a class missing from the cache, project_import refresh_classes rewrites the cache from disk at the cost of a short headless engine, which matters beside a running bench.",
|
|
12839
12870
|
parameters: {
|
|
12840
12871
|
projectPath: PROJECT_PATH,
|
|
12841
12872
|
scriptPath: {
|
|
@@ -12928,7 +12959,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12928
12959
|
create_shader: { effect: "destructive", summary: "a .gdshader file", requires: ["shaderType"] },
|
|
12929
12960
|
create_tileset: {
|
|
12930
12961
|
effect: "destructive",
|
|
12931
|
-
summary: "a TileSet from texture atlases",
|
|
12962
|
+
summary: "a TileSet from texture atlases; its physics, terrain and custom data layers, and each tile's collision and other values, are written with modify after it",
|
|
12932
12963
|
requires: ["sources"]
|
|
12933
12964
|
},
|
|
12934
12965
|
set_theme_color: {
|
|
@@ -12951,7 +12982,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
12951
12982
|
{
|
|
12952
12983
|
name: "editor_launch",
|
|
12953
12984
|
title: "Open, restart or close the editor",
|
|
12954
|
-
description: "Opens the Godot editor on a project, or restarts or closes the one already connected. close saves open scenes, quits the editor and waits for its process to go, which is the only way to end a hidden one short of killing it; settingsDropped in its answer
|
|
12985
|
+
description: "Opens the Godot editor on a project, or restarts or closes the one already connected. close saves open scenes, quits the editor and waits for its process to go, which is the only way to end a hidden one short of killing it; settingsDropped in its answer names what that save took out of project.godot, and is left out when it took nothing; settingsNote says so when the file could not be read to tell. An editor this server opened that has not connected yet has nothing of this server's to save, so close stops its process instead and answers beforeConnecting. open answers once the process has started, and the editor dials in after its import; a call needing the editor made before then waits for the one this server opened, for as long as a restart waits, and is refused naming it if it has not arrived. open refuses while an editor of the project is already running and has not reached this server, naming its pid, rather than putting a second on the project. The editor is an ordinary visible one on the desktop in use, and on Windows it is shown without being activated, so opening or reopening it does not take the keyboard from whatever the user is typing in. hidden: true opens it headless instead and, on Windows, on a desktop of its own, where the games it plays go too; a hidden editor serves the bridge, the language server and the debug adapter as a visible one does. A game a visible editor plays opens as a window on the desktop in use. An editor goes on serving the addon it read at startup, so restart is what puts a gdharness upgrade into effect, and nothing else here restarts one; it saves open scenes on the way out and answers with the version that came back. An editor a server opened is started again by the server, visible unless hidden: true is passed again, once the old one has gone: it waits 90 seconds for that, or GDHARNESS_EDITOR_RESTART_TIMEOUT_MS, and an old editor still running after it is not replaced, since the new one would find its ports held. One opened by hand restarts itself, which only one with a window can do, because the engine hands back none of the arguments it was started with. editor_status says which editor is connected and whether it is holding an old addon. Opening a project is a save and so is closing one, which is the part that is not obvious from outside: the editor imports the project on open and writes project.godot back, and Godot writes only what differs from its own defaults, so a key named deliberately at its default value is dropped either way. A restart says which under settingsDropped in its own answer because it waits for the editor to return. An open cannot, since it answers as soon as the process exists and the save happens during the import minutes later, so editor_status carries that reading once the editor has connected. Nothing else will say a key went until something depends on one. A restart of an editor this server opened is a quit and then a launch, and this server can be ended between them, usually by the reconnect the restart was being taken for: the editor is gone and nothing replaces it. That is written down before the quit, so the next server says so under restartInterrupted in editor_status rather than waiting for an editor that is not coming, and open finishes it, saying so under finishesRestart. An open is refused when the editor it would start could never reach this server: a project other than the one this server serves, whose editor dials that project's own server; a project without the gdharness editor addon installed and enabled; and a project whose editor a restart is already bringing back.",
|
|
12955
12986
|
parameters: {
|
|
12956
12987
|
projectPath: { ...PROJECT_PATH, ops: ["open"] },
|
|
12957
12988
|
hidden: {
|
|
@@ -13188,7 +13219,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
13188
13219
|
title: "Editor status",
|
|
13189
13220
|
effect: "read",
|
|
13190
13221
|
description: "Whether the editor addon is connected, which Godot answers, whether the editor is playing something, and which games with the runtime addon are reachable, of this project and of every other on the machine. Read connected with mayYetConnect: the editor dials this server and backs off between tries, so for the first half-minute after a server starts false means not reached yet as often as no editor; mayYetConnect true is worth waiting out, false is final, and editorCannotConnect, restartInterrupted, restartUnderway, closedHere and editorsNotYetConnected say why. An editor that has connected and not yet greeted reports nothing about itself, and every other call made in that window waits up to ten seconds for it to settle. playingInEditor null means unanswered rather than nothing playing: processActive and runtimes do not depend on the editor answering. game.run names the run editor_output and editor_run stop answer for, and stays named after it ends. addonIsStale, on a connected editor and on each running game (absent with neither), says it runs addon code other than what this server ships, and staleNote says which half moves: the project, by a gdharness upgrade it spells out to run in a shell, the editor by a restart, or this server by a reconnect. A false editor.lspListening or editor.dapListening comes with serversNote, and editor_launch restart binds the port again. editor.scan says whether the editor is scanning, which editor_run waits out before starting a game. A game announced in a protocol this server does not speak is listed under unreadable, during an upgrade that moves the protocol, until the halves match.",
|
|
13191
|
-
answer: "projectIs, when present, is the gdharness version of the addons in the project, which differs from this server's (project_info says which of the two to move), and configIs, when present, the version the project's MCP config starts, which differs from this server's, so the next connection runs that one. server names this server: its pid, its version, and lifecycleLog, the file every gdharness server of the user appends a line to when it starts, when its client first names itself, when it replaces another server of its project, and when it ends, with why it ended (the client closing its end as stdin:end, a signal by name, superseded with the successor's pid, an uncaught exception or rejection with its stack, or the exit code) and the calls it was answering then. The parent's command line follows on its own line a few seconds after the start. A server killed without warning writes no ended line, and on Windows every kill is that, so a started line with no ended line after it is a server something killed. " + "runtimeConnected counts the games of the project this server serves, and runtimes lists every game on the machine with ofThisProject saying which is which, since a game of another project is reached only by naming its projectPath. playingInEditor is null when the editor was not asked or did not answer, which is not the same as a no: with no editor connected there is nobody to ask, and an editor that does not serve the question is given a moment and then left. A game can be playing while this is null, so read it as unanswered rather than as nothing playing, and use processActive and runtimes, which come from elsewhere and do not depend on the editor answering. Its play says which play the editor is on: play.play counts the plays that editor has started since it opened, whoever started them, and play.editorPid is the editor, so two reads with different pairs are two plays even when both say playing. game.run names the run processActive is about, the one editor_output and editor_run stop answer for: its pid, its project, and adopted true when this server read it back from another server rather than starting it. It stays named after the run ends, beside processActive false, so editor_output can still read what that run printed; null when there is no run at all. startedAt says when it began, and endedAt when it ended, wherever something saw the end: a run adopted from a note another server wrote can have ended hours before this server started. editor.lspListening and editor.dapListening say whether anything accepts connections on the ports the editor names, lspPort and dapPort: Godot binds each once, as the editor starts, and reports a failure only in the log panel of the editor itself, so a false comes with serversNote, and editor_launch restart binds it again. editor.scan says whether the editor is scanning or importing and how many milliseconds ago its last scan finished (finishedMsAgo), or is null when it did not answer: the editor rewrites the class cache just after a scan, and editor_run waits that out before starting a game, saying so under waitedForEditorScanMs. Each game under runtimes is pinged with a short wait, so one held at a breakpoint is listed as unreachable rather than making this call wait out the runtime timeout; for the run this server is reporting on, heldAt says whether that is what it is, with the same three answers editor_output gives. A game the editor played announces the editor under editorPid, and so does whatever that game started for itself; a game some other server started announces none, which is how the two are told apart when both are running from one project. Each game also says which runtime addon it loaded, under addonVersion (null when it cannot say); addonIsStale is true when that code is not what this server ships, and staleNote says whether the project needs the gdharness upgrade command, spelled out to run in a shell, the game a restart, or this server a reconnect. A second checkout of a project, such as a git worktree, carries addons of its own and is where this shows. A runtime_* call to such a game is refused with the staleNote and not sent. When connected is false, mayYetConnect says whether that is final: the editor dials this server rather than the other way round and backs off between tries, so for the first half-minute after a server starts, false means \"not reached yet\" as often as it means \"no editor\". True is worth waiting out; false is an editor that is not there. False beside editorCannotConnect is a project without the gdharness editor addon installed or enabled, where no editor can ever dial in, however young the server or whichever editor is open; its remedies say how to install or enable it. False beside restartInterrupted is one that an editor_launch restart on a previous server asked to quit, where the launch half never ran because that server was ended in between, usually by the reconnect the restart was taken for; editor_launch open finishes it. True beside restartUnderway is a restart still in progress, its server alive and within the wait for the old editor to go: the editor is coming, and opening another would put two on one project. listeningSince is when this server took the bridge port, which is what that window is measured from and what a caller wanting its own window should read. An editor this server opened counts for as long as its process lives, however far past that window the import runs, and awaitingLaunchedEditor names its pid so the two reasons for true are told apart. Any editor of this project running and not yet connected, whoever opened it, makes it true as well and is named under editorsNotYetConnected with its pid and start time, so a restart a reconnect interrupted after its launch is not read as nothing being there. settingsDropped appears here once when the editor this server opened saved project.godot on its way in, which is the same reading editor_launch restart makes in its own answer. A game that has announced itself in a protocol this server does not speak is listed under unreadable rather than left out, with the protocol it speaks and whether the server or the addon is the older half. This happens during an upgrade that moves the runtime protocol, which most do not: installing replaces the addon on disk as soon as the pin moves, while a server that is already running stays on the version it started with, so the two speak different protocols until the server is reconnected. Those games are real and running, but no tool here can reach them until the halves match, so runtimes stays empty and runtimeConnected stays false. An upgrade that leaves the protocol alone opens no such window and this list stays empty through it. addonIsStale is decided by the code of the editor addons rather than their version, so an editor started before an upgrade that left that code alone reports the older addonVersion, is not stale, and addonNote says so: it needs no restart. A stale editor is asked nothing but to quit: every other call to it is refused with staleNote, which names editor_launch restart, the upgrade command or a reconnect. port is the one the editor bridge is on; when that is not the one this server was configured with, portWanted names the configured one and portNote says why it moved and, when it was the server this one replaced, which pid kept it. A server replacing another of its project that holds the configured port waits for it to stand down and takes the port over, which takes a few seconds; bridgeHandover says so while it waits, and it moves only if that server has not let go within the wait. An editor that has connected and not yet greeted, which lasts a frame and longer while it imports, reports nothing about itself: greeting says so, addonIsStale is absent rather than guessed, and a restart asked then waits for the greeting to learn who opened it. startedByAnEditor is an editor another editor started, by Godot's own restart or the project manager, which has none of the arguments a server gave the one before it; startedByAnEditorNote says what that costs. An engine run that loads the editor addon to do one job and quit, such as a gate's godot --headless --import, an export or a script, is not taken as the editor: a process that greets without a server's mark has its command line read first, and while that is read identifying is true and connected false; one started with such an option is turned away, and turnedAway names the last one, its pid and the option. Every other call made while an editor is arriving, before its greeting or while it is looked up, waits up to ten seconds for it to settle rather than acting on connected as it reads in that window. serverVersion is the gdharness version of this server. bridgeAvailable says the editor bridge is listening; when it failed to start, startupError gives the error, and retryingBridge is true while this server tries again. announcedAt is the file where this server told editors of its project which port to dial. connectedAt is when the editor connected, and lastPongAt when it last answered this server's keep-alive ping. addonDigest is a hash of the editor addon's code, which addonIsStale compares with what this server ships. debugPort is the port of the editor's remote debugger, the one games it plays connect to. openedByAServer says a gdharness server started this editor, and syncsBreakpoints that it keeps its breakpoints when a debug session opens, which Godot otherwise clears. pendingRequests counts the requests sent to the editor and not yet answered, and queuedResources the files with writes waiting behind another write to the same file.",
|
|
13222
|
+
answer: "projectIs, when present, is the gdharness version of the addons in the project, which differs from this server's (project_info says which of the two to move), and configIs, when present, the version the project's MCP config starts, which differs from this server's, so the next connection runs that one. server names this server: its pid, its version, and lifecycleLog, the file every gdharness server of the user appends a line to when it starts, when its client first names itself, when it replaces another server of its project, and when it ends, with why it ended (the client closing its end as stdin:end, a signal by name, superseded with the successor's pid, an uncaught exception or rejection with its stack, or the exit code) and the calls it was answering then. The parent's command line follows on its own line a few seconds after the start. A server killed without warning writes no ended line, and on Windows every kill is that, so a started line with no ended line after it is a server something killed. " + "runtimeConnected counts the games of the project this server serves, and runtimes lists every game on the machine with ofThisProject saying which is which, since a game of another project is reached only by naming its projectPath. playingInEditor is null when the editor was not asked or did not answer, which is not the same as a no: with no editor connected there is nobody to ask, and an editor that does not serve the question is given a moment and then left. A game can be playing while this is null, so read it as unanswered rather than as nothing playing, and use processActive and runtimes, which come from elsewhere and do not depend on the editor answering. Its play says which play the editor is on: play.play counts the plays that editor has started since it opened, whoever started them, and play.editorPid is the editor, so two reads with different pairs are two plays even when both say playing. game.run names the run processActive is about, the one editor_output and editor_run stop answer for: its pid, its project, and adopted true when this server read it back from another server rather than starting it. It stays named after the run ends, beside processActive false, so editor_output can still read what that run printed; null when there is no run at all. startedAt says when it began, and endedAt when it ended, wherever something saw the end: a run adopted from a note another server wrote can have ended hours before this server started. editor.lspListening and editor.dapListening say whether anything accepts connections on the ports the editor names, lspPort and dapPort: Godot binds each once, as the editor starts, and reports a failure only in the log panel of the editor itself, so a false comes with serversNote, and editor_launch restart binds it again. editor.scan says whether the editor is scanning or importing and how many milliseconds ago its last scan finished (finishedMsAgo), or is null when it did not answer: the editor rewrites the class cache just after a scan, and editor_run waits that out before starting a game, saying so under waitedForEditorScanMs. Each game under runtimes is pinged with a short wait, so one held at a breakpoint is listed as unreachable rather than making this call wait out the runtime timeout; for the run this server is reporting on, heldAt says whether that is what it is, with the same three answers editor_output gives. A game the editor played announces the editor under editorPid, and so does whatever that game started for itself; a game some other server started announces none, which is how the two are told apart when both are running from one project. Each game also says which runtime addon it loaded, under addonVersion (null when it cannot say); addonIsStale is true when that code is not what this server ships, and staleNote says whether the project needs the gdharness upgrade command, spelled out to run in a shell, the game a restart, or this server a reconnect. A second checkout of a project, such as a git worktree, carries addons of its own and is where this shows. A runtime_* call to such a game is refused with the staleNote and not sent. When connected is false, mayYetConnect says whether that is final: the editor dials this server rather than the other way round and backs off between tries, so for the first half-minute after a server starts, false means \"not reached yet\" as often as it means \"no editor\". True is worth waiting out; false is an editor that is not there. False beside editorCannotConnect is a project without the gdharness editor addon installed or enabled, where no editor can ever dial in, however young the server or whichever editor is open; its remedies say how to install or enable it. False beside restartInterrupted is one that an editor_launch restart on a previous server asked to quit, where the launch half never ran because that server was ended in between, usually by the reconnect the restart was taken for; editor_launch open finishes it. True beside restartUnderway is a restart still in progress, its server alive and within the wait for the old editor to go: the editor is coming, and opening another would put two on one project. listeningSince is when this server took the bridge port, which is what that window is measured from and what a caller wanting its own window should read. An editor this server opened counts for as long as its process lives, however far past that window the import runs, and awaitingLaunchedEditor names its pid so the two reasons for true are told apart. Any editor of this project running and not yet connected, whoever opened it, makes it true as well and is named under editorsNotYetConnected with its pid and start time, so a restart a reconnect interrupted after its launch is not read as nothing being there. settingsDropped appears here once when the editor this server opened saved project.godot on its way in and took a key out of it, which is the same reading editor_launch restart makes in its own answer. A game that has announced itself in a protocol this server does not speak is listed under unreadable rather than left out, with the protocol it speaks and whether the server or the addon is the older half. This happens during an upgrade that moves the runtime protocol, which most do not: installing replaces the addon on disk as soon as the pin moves, while a server that is already running stays on the version it started with, so the two speak different protocols until the server is reconnected. Those games are real and running, but no tool here can reach them until the halves match, so runtimes stays empty and runtimeConnected stays false. An upgrade that leaves the protocol alone opens no such window and this list stays empty through it. addonIsStale is decided by the code of the editor addons rather than their version, so an editor started before an upgrade that left that code alone reports the older addonVersion, is not stale, and addonNote says so: it needs no restart. A stale editor is asked nothing but to quit: every other call to it is refused with staleNote, which names editor_launch restart, the upgrade command or a reconnect. port is the one the editor bridge is on; when that is not the one this server was configured with, portWanted names the configured one and portNote says why it moved and, when it was the server this one replaced, which pid kept it. A server replacing another of its project that holds the configured port waits for it to stand down and takes the port over, which takes a few seconds; bridgeHandover says so while it waits, and it moves only if that server has not let go within the wait. An editor that has connected and not yet greeted, which lasts a frame and longer while it imports, reports nothing about itself: greeting says so, addonIsStale is absent rather than guessed, and a restart asked then waits for the greeting to learn who opened it. startedByAnEditor is an editor another editor started, by Godot's own restart or the project manager, which has none of the arguments a server gave the one before it; startedByAnEditorNote says what that costs. An engine run that loads the editor addon to do one job and quit, such as a gate's godot --headless --import, an export or a script, is not taken as the editor: a process that greets without a server's mark has its command line read first, and while that is read identifying is true and connected false; one started with such an option is turned away, and turnedAway names the last one, its pid and the option. Every other call made while an editor is arriving, before its greeting or while it is looked up, waits up to ten seconds for it to settle rather than acting on connected as it reads in that window. serverVersion is the gdharness version of this server. bridgeAvailable says the editor bridge is listening; when it failed to start, startupError gives the error, and retryingBridge is true while this server tries again. announcedAt is the file where this server told editors of its project which port to dial. connectedAt is when the editor connected, and lastPongAt when it last answered this server's keep-alive ping. addonDigest is a hash of the editor addon's code, which addonIsStale compares with what this server ships. debugPort is the port of the editor's remote debugger, the one games it plays connect to. openedByAServer says a gdharness server started this editor, and syncsBreakpoints that it keeps its breakpoints when a debug session opens, which Godot otherwise clears. pendingRequests counts the requests sent to the editor and not yet answered, and queuedResources the files with writes waiting behind another write to the same file.",
|
|
13192
13223
|
parameters: {},
|
|
13193
13224
|
requires: []
|
|
13194
13225
|
},
|
|
@@ -13542,7 +13573,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
13542
13573
|
minimum: 1,
|
|
13543
13574
|
maximum: 600,
|
|
13544
13575
|
ops: ["action", "key", "mouse_click", "joypad_button"],
|
|
13545
|
-
description: "action, key, mouse_click, joypad_button: hold a whole press down for this many process frames and then let go, both inside the game, so a pour, a charge or a long press runs to a set length. A press, a frames wait and a release sent as three calls hold it for the time between the calls as well. The answer says held_frames. Not with pressed, and not on a wheel step. Default 1."
|
|
13576
|
+
description: "action, key, mouse_click, joypad_button: hold a whole press down for this many process frames and then let go, both inside the game, so a pour, a charge or a long press runs to a set length. A press, a frames wait and a release sent as three calls hold it for the time between the calls as well. The answer says held_frames, and under held_for the seconds the hold lasted and the physics_frames that ran in it: a process frame is no set time, and a headless game, drawing nothing, runs them far faster than the sixty physics ticks a second that _physics_process sees. Not with pressed, and not on a wheel step. Default 1."
|
|
13546
13577
|
},
|
|
13547
13578
|
strength: {
|
|
13548
13579
|
type: "number",
|
|
@@ -39535,7 +39566,8 @@ async function renameSymbol(request, services) {
|
|
|
39535
39566
|
};
|
|
39536
39567
|
}
|
|
39537
39568
|
if (newName === symbol) {
|
|
39538
|
-
|
|
39569
|
+
const moving = request.newScriptPath === null ? "" : " resource_edit move moves the script alone, with every path in the project naming it.";
|
|
39570
|
+
return { ok: false, reason: `${symbol} is already called ${newName}; nothing to rename.${moving}` };
|
|
39539
39571
|
}
|
|
39540
39572
|
const declaringPath = resourcePathOf(projectPath, request.scriptPath);
|
|
39541
39573
|
if (declaringPath === null) {
|
|
@@ -45709,19 +45741,37 @@ function describeValue(value) {
|
|
|
45709
45741
|
return VALUE_NAMES[typeof value] ?? typeof value;
|
|
45710
45742
|
}
|
|
45711
45743
|
function wrongTypes(spec, args) {
|
|
45712
|
-
|
|
45713
|
-
|
|
45714
|
-
|
|
45715
|
-
|
|
45744
|
+
return Object.entries(args).flatMap(([name, value]) => misshapen(spec.parameters[name], value, name));
|
|
45745
|
+
}
|
|
45746
|
+
function misshapen(schema, value, path) {
|
|
45747
|
+
if (!isPlainObject3(schema) || value === undefined || value === null) {
|
|
45748
|
+
return [];
|
|
45749
|
+
}
|
|
45750
|
+
const declared = schema["type"];
|
|
45751
|
+
const wanted = typeof declared === "string" ? [declared] : Array.isArray(declared) ? declared.filter((kind) => typeof kind === "string") : [];
|
|
45752
|
+
if (wanted.length > 0 && !wanted.some((kind) => isOfType(value, kind))) {
|
|
45753
|
+
return [`${path} as ${wanted.join(" or ")}, not ${describeValue(value)}`];
|
|
45754
|
+
}
|
|
45755
|
+
if (Array.isArray(value)) {
|
|
45756
|
+
return value.flatMap((element, index) => misshapen(schema["items"], element, `${path}[${index}]`));
|
|
45757
|
+
}
|
|
45758
|
+
const properties = schema["properties"];
|
|
45759
|
+
if (!isPlainObject3(properties) || !isPlainObject3(value)) {
|
|
45760
|
+
return [];
|
|
45761
|
+
}
|
|
45762
|
+
return Object.entries(value).flatMap(([field, held]) => {
|
|
45763
|
+
if (Object.hasOwn(properties, field)) {
|
|
45764
|
+
return misshapen(properties[field], held, `${path}.${field}`);
|
|
45716
45765
|
}
|
|
45717
|
-
|
|
45718
|
-
|
|
45719
|
-
if (wanted.length === 0 || wanted.some((kind) => isOfType(value, kind))) {
|
|
45720
|
-
continue;
|
|
45766
|
+
if (schema["additionalProperties"] !== false) {
|
|
45767
|
+
return [];
|
|
45721
45768
|
}
|
|
45722
|
-
|
|
45723
|
-
|
|
45724
|
-
|
|
45769
|
+
const fields = Object.keys(properties);
|
|
45770
|
+
const close = nearest(field, fields);
|
|
45771
|
+
return [
|
|
45772
|
+
`${path} with only the fields ${fields.join(", ")}, and ${field} is none of them${close.length === 0 ? "" : ` (the nearest is ${close[0]})`}`
|
|
45773
|
+
];
|
|
45774
|
+
});
|
|
45725
45775
|
}
|
|
45726
45776
|
function unlistedValues(schema, value, path) {
|
|
45727
45777
|
if (typeof schema !== "object" || schema === null) {
|
|
@@ -47603,34 +47653,8 @@ class GodotServer {
|
|
|
47603
47653
|
}
|
|
47604
47654
|
return { ok: true, value: { path, file } };
|
|
47605
47655
|
}
|
|
47606
|
-
gameArguments(args) {
|
|
47607
|
-
if (args["args"] === undefined) {
|
|
47608
|
-
return { ok: true, value: [] };
|
|
47609
|
-
}
|
|
47610
|
-
const given = readStringArray(args, "args");
|
|
47611
|
-
if (given === undefined) {
|
|
47612
|
-
return {
|
|
47613
|
-
ok: false,
|
|
47614
|
-
response: this.createErrorResponse("args must be a list of strings.", [
|
|
47615
|
-
`Pass the game's own flags, such as ["--level=2"]`
|
|
47616
|
-
])
|
|
47617
|
-
};
|
|
47618
|
-
}
|
|
47619
|
-
return { ok: true, value: given };
|
|
47620
|
-
}
|
|
47621
47656
|
engineArguments(args) {
|
|
47622
|
-
|
|
47623
|
-
return { ok: true, value: [] };
|
|
47624
|
-
}
|
|
47625
|
-
const given = readStringArray(args, "engineArgs");
|
|
47626
|
-
if (given === undefined) {
|
|
47627
|
-
return {
|
|
47628
|
-
ok: false,
|
|
47629
|
-
response: this.createErrorResponse("engineArgs must be a list of strings.", [
|
|
47630
|
-
'Pass engine flags, such as ["--verbose"] or ["--fixed-fps", "60"]'
|
|
47631
|
-
])
|
|
47632
|
-
};
|
|
47633
|
-
}
|
|
47657
|
+
const given = readStringArray(args, "engineArgs") ?? [];
|
|
47634
47658
|
const checked = engineFlags(given);
|
|
47635
47659
|
if (!checked.ok) {
|
|
47636
47660
|
return { ok: false, response: this.createErrorResponse(checked.reason) };
|
|
@@ -48032,6 +48056,16 @@ class GodotServer {
|
|
|
48032
48056
|
...params
|
|
48033
48057
|
} = contained.value;
|
|
48034
48058
|
const written = await this.operation("set_import_options", params, project.value.path);
|
|
48059
|
+
const changed = written.ok ? written.payload["updated_options"] : null;
|
|
48060
|
+
if (written.ok && Array.isArray(changed) && changed.length === 0) {
|
|
48061
|
+
return this.answer({
|
|
48062
|
+
...written,
|
|
48063
|
+
payload: {
|
|
48064
|
+
...written.payload,
|
|
48065
|
+
note: "Not reimported: every option given already held that value, so the import file was not written."
|
|
48066
|
+
}
|
|
48067
|
+
});
|
|
48068
|
+
}
|
|
48035
48069
|
if (!written.ok || args["reimport"] === false) {
|
|
48036
48070
|
return this.answer(written.ok ? {
|
|
48037
48071
|
...written,
|
|
@@ -49906,10 +49940,7 @@ class GodotServer {
|
|
|
49906
49940
|
if (exported !== null && readBoolean(args, "profile") === true) {
|
|
49907
49941
|
return this.createErrorResponse("A profile is read through the debugger, and an exported build is started without one, since a release build quits when given --remote-debug. Profile the project without executable.");
|
|
49908
49942
|
}
|
|
49909
|
-
const given =
|
|
49910
|
-
if (!given.ok) {
|
|
49911
|
-
return given.response;
|
|
49912
|
-
}
|
|
49943
|
+
const given = readStringArray(args, "args") ?? [];
|
|
49913
49944
|
const flags = this.engineArguments(args);
|
|
49914
49945
|
if (!flags.ok) {
|
|
49915
49946
|
return flags.response;
|
|
@@ -49941,7 +49972,7 @@ class GodotServer {
|
|
|
49941
49972
|
const scanned = await this.afterTheImport(project.value.path, waited, imported);
|
|
49942
49973
|
const sceneArgument = sceneToRun?.ok ? sceneToRun.relativePath : null;
|
|
49943
49974
|
if (op === "check") {
|
|
49944
|
-
return await this.checkBoot(engine.value, project.value.path, sceneArgument, args, given
|
|
49975
|
+
return await this.checkBoot(engine.value, project.value.path, sceneArgument, args, given, scanned, asked.value, flags.value);
|
|
49945
49976
|
}
|
|
49946
49977
|
await this.pickUpWhatTheEditorIsPlaying();
|
|
49947
49978
|
let ended = null;
|
|
@@ -49970,14 +50001,14 @@ class GodotServer {
|
|
|
49970
50001
|
const silent = resolveSilent(args["silent"]) && !headless;
|
|
49971
50002
|
const silentOnlyHere = silent && !editorPlaysHeadless(project.value.file);
|
|
49972
50003
|
const profiled = readBoolean(args, "profile") === true;
|
|
49973
|
-
if (exported === null && this.godotBridge.isConnected() && editorWouldPlay && given.
|
|
50004
|
+
if (exported === null && this.godotBridge.isConnected() && editorWouldPlay && given.length === 0 && flags.value.length === 0 && !needsItsOwnProcess(asked.value) && !silentOnlyHere) {
|
|
49974
50005
|
return await this.playThroughEditor(sceneArgument, refreshed.value, scanned, project.value.path, alreadyPlaying, runtimeWaitMs, ended, profiled);
|
|
49975
50006
|
}
|
|
49976
50007
|
const cmdArgs = runArguments({
|
|
49977
50008
|
projectPath: exported === null ? project.value.path : null,
|
|
49978
50009
|
headless,
|
|
49979
50010
|
scene: sceneArgument,
|
|
49980
|
-
userArgs: given
|
|
50011
|
+
userArgs: given,
|
|
49981
50012
|
engineArgs: flags.value,
|
|
49982
50013
|
silent
|
|
49983
50014
|
});
|
|
@@ -49991,7 +50022,7 @@ class GodotServer {
|
|
|
49991
50022
|
started.announcedBefore = alreadyPlaying;
|
|
49992
50023
|
started.bootScene = runtimeWaitMs.scene;
|
|
49993
50024
|
this.activeProcess = started;
|
|
49994
|
-
const spawnedInstead = exported !== null ? " An exported build is started without a debugger, since a release build quits when given one, so breakpoints and debug_state do not reach it." : this.godotBridge.isConnected() && editorWouldPlay && (given.
|
|
50025
|
+
const spawnedInstead = exported !== null ? " An exported build is started without a debugger, since a release build quits when given one, so breakpoints and debug_state do not reach it." : this.godotBridge.isConnected() && editorWouldPlay && (given.length > 0 || flags.value.length > 0) ? ` The editor cannot be handed arguments for a game it plays, so this one was started here.${OWN_DEBUGGER}` : this.godotBridge.isConnected() && editorWouldPlay && needsItsOwnProcess(asked.value) ? ` The editor plays a game with its own environment, so a run given one was started here.${OWN_DEBUGGER}` : this.godotBridge.isConnected() && editorWouldPlay && silentOnlyHere ? " The editor cannot play a game silent, which takes an engine flag, so this one was " + `started here, silent as every run is unless asked otherwise, and silent: false plays it through the editor, with sound.${OWN_DEBUGGER}` : "";
|
|
49995
50026
|
const endedForThis = endedToStartThis(ended);
|
|
49996
50027
|
const stranded = wereHereFirst.filter((one) => one.pid !== ended?.pid && alive(one.pid));
|
|
49997
50028
|
const handed = this.dapHoldingBreakpointsOf(project.value.path).breakpointsHeld();
|
|
@@ -50004,7 +50035,7 @@ class GodotServer {
|
|
|
50004
50035
|
executable: exported?.ok === true ? exported.relativePath : undefined,
|
|
50005
50036
|
scene: exported !== null ? undefined : sceneArgument === null ? mainSceneOf(project.value.file) : `res://${sceneArgument}`,
|
|
50006
50037
|
arguments: cmdArgs,
|
|
50007
|
-
argsNote: engineFlagsNote(given
|
|
50038
|
+
argsNote: engineFlagsNote(given),
|
|
50008
50039
|
transcript: started.transcript,
|
|
50009
50040
|
breakpoints: started.keeper === undefined || handed.length === 0 ? undefined : this.breakpointsAsProjectSpells(project.value.path, handed),
|
|
50010
50041
|
profile: profileOnStart(profiled, "gdharness", runtimeAddonRegistered(project.value.path)),
|
|
@@ -50014,7 +50045,7 @@ class GodotServer {
|
|
|
50014
50045
|
endedPreviousRun: endedPreviousRun(ended),
|
|
50015
50046
|
previousRunLeft: previousRunLeft(ended),
|
|
50016
50047
|
...previousRunHow(ended),
|
|
50017
|
-
runtime: exported !== null ? undefined : await this.runtimeUp(project.value.path, alreadyPlaying, runtimeWaitMs, given.
|
|
50048
|
+
runtime: exported !== null ? undefined : await this.runtimeUp(project.value.path, alreadyPlaying, runtimeWaitMs, given.length > 0),
|
|
50018
50049
|
message: `Use editor_output for what it prints and editor_run stop to end it.${started.keeper !== undefined && handed.length > 0 ? " It stops at the lines under breakpoints, and debug_state stack reads where it is held." : ""}${spawnedInstead}${endedForThis}${alsoRunning}`
|
|
50019
50050
|
});
|
|
50020
50051
|
}
|
|
@@ -164,8 +164,9 @@ static func state_machine(tree: AnimationTree, state_machine_path: String) -> An
|
|
|
164
164
|
static func no_machine(tree: AnimationTree, state_machine_path: String) -> String:
|
|
165
165
|
if tree == null or tree.tree_root == null:
|
|
166
166
|
return (
|
|
167
|
-
"The AnimationTree has no tree_root.
|
|
168
|
-
+ "AnimationNodeStateMachine
|
|
167
|
+
"The AnimationTree has no tree_root. Give it one with scene_node set: tree_root "
|
|
168
|
+
+ '{"_type": "AnimationNodeStateMachine"} builds one into the scene, and the res:// path '
|
|
169
|
+
+ "of one made with resource_edit create keeps it in a file of its own."
|
|
169
170
|
)
|
|
170
171
|
var current: AnimationNodeStateMachine = tree.tree_root as AnimationNodeStateMachine
|
|
171
172
|
if current == null:
|