gdharness 1.2.14 → 1.2.16
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 +393 -80
- package/build/godot/addons/gdharness_editor/property_values.gd +28 -0
- package/build/godot/addons/gdharness_editor/scene_file.gd +27 -8
- package/build/godot/addons/gdharness_editor/serialisation.gd +20 -0
- package/build/godot/addons/gdharness_editor/tool_executor.gd +4 -1
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +172 -0
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +60 -47
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +46 -4
- package/build/godot/addons/gdharness_runtime/runtime_capture.gd +13 -3
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +1 -17
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +29 -3
- package/build/godot/addons/gdharness_runtime/serialisation.gd +20 -0
- package/build/godot/operations/audio_buses.gd +35 -0
- package/build/godot/operations/classdb_queries.gd +31 -2
- package/build/godot/operations/file_walk.gd +9 -2
- package/build/godot/operations/gdscript_authoring.gd +4 -5
- package/build/godot/operations/godot_operations.gd +4 -0
- package/build/godot/operations/input_actions.gd +27 -0
- package/build/godot/operations/project_config.gd +8 -1
- package/build/godot/operations/project_diagnostics.gd +9 -5
- package/build/godot/operations/serialisation.gd +20 -0
- package/build/index.js +380 -66
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -9852,16 +9852,6 @@ var init_class_cache = __esm(() => {
|
|
|
9852
9852
|
TOOL = /^[ \t]*(?:@[a-z_]+(?:\([^)\n]*\))?[ \t]+)*@tool\b/m;
|
|
9853
9853
|
});
|
|
9854
9854
|
|
|
9855
|
-
// src/answer-json.ts
|
|
9856
|
-
function answerJson(value) {
|
|
9857
|
-
return JSON.stringify(value, null, 2).replace(SCALAR_ARRAY, (_whole, items) => `[${items.split(/,\n\s+/).join(", ")}]`);
|
|
9858
|
-
}
|
|
9859
|
-
var SCALAR, SCALAR_ARRAY;
|
|
9860
|
-
var init_answer_json = __esm(() => {
|
|
9861
|
-
SCALAR = String.raw`(?:-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)`;
|
|
9862
|
-
SCALAR_ARRAY = new RegExp(String.raw`\[\n\s+(${SCALAR}(?:,\n\s+${SCALAR})*)\n\s*\]`, "g");
|
|
9863
|
-
});
|
|
9864
|
-
|
|
9865
9855
|
// src/project-scan.ts
|
|
9866
9856
|
import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync8 } from "node:fs";
|
|
9867
9857
|
import { extname, join as join10 } from "node:path";
|
|
@@ -9869,8 +9859,14 @@ function skipped(name) {
|
|
|
9869
9859
|
return name.startsWith(".") || SKIPPED.has(name);
|
|
9870
9860
|
}
|
|
9871
9861
|
function steppedOver(directory) {
|
|
9862
|
+
return gdignored(directory) || installedByUs(directory);
|
|
9863
|
+
}
|
|
9864
|
+
function gdignored(directory) {
|
|
9872
9865
|
return existsSync10(join10(directory, ".gdignore"));
|
|
9873
9866
|
}
|
|
9867
|
+
function installedByUs(directory) {
|
|
9868
|
+
return existsSync10(join10(directory, VERSION_MARKER));
|
|
9869
|
+
}
|
|
9874
9870
|
function projectStructure(projectPath) {
|
|
9875
9871
|
const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
|
|
9876
9872
|
const visit = (directory) => {
|
|
@@ -9983,7 +9979,10 @@ function projectTexts(projectPath) {
|
|
|
9983
9979
|
function ignoredTexts(projectPath) {
|
|
9984
9980
|
const found = [];
|
|
9985
9981
|
const visit = (directory, prefix, ignored) => {
|
|
9986
|
-
|
|
9982
|
+
if (installedByUs(directory)) {
|
|
9983
|
+
return;
|
|
9984
|
+
}
|
|
9985
|
+
const under = ignored || gdignored(directory);
|
|
9987
9986
|
for (const entry of readdirSync5(directory, { withFileTypes: true })) {
|
|
9988
9987
|
if (skipped(entry.name)) {
|
|
9989
9988
|
continue;
|
|
@@ -10065,7 +10064,7 @@ function searchProject(projectPath, options) {
|
|
|
10065
10064
|
visit(projectPath);
|
|
10066
10065
|
return result;
|
|
10067
10066
|
}
|
|
10068
|
-
var SKIPPED, SCENE_EXTENSIONS, ASSET_EXTENSIONS, CARRIES_A_UID, BINARY_EXTENSIONS;
|
|
10067
|
+
var SKIPPED, VERSION_MARKER = ".gdharness-version", SCENE_EXTENSIONS, ASSET_EXTENSIONS, CARRIES_A_UID, BINARY_EXTENSIONS;
|
|
10069
10068
|
var init_project_scan = __esm(() => {
|
|
10070
10069
|
SKIPPED = new Set(["node_modules"]);
|
|
10071
10070
|
SCENE_EXTENSIONS = new Set(["tscn", "scn"]);
|
|
@@ -10113,6 +10112,16 @@ var init_project_scan = __esm(() => {
|
|
|
10113
10112
|
]);
|
|
10114
10113
|
});
|
|
10115
10114
|
|
|
10115
|
+
// src/answer-json.ts
|
|
10116
|
+
function answerJson(value) {
|
|
10117
|
+
return JSON.stringify(value, null, 2).replace(SCALAR_ARRAY, (_whole, items) => `[${items.split(/,\n\s+/).join(", ")}]`);
|
|
10118
|
+
}
|
|
10119
|
+
var SCALAR, SCALAR_ARRAY;
|
|
10120
|
+
var init_answer_json = __esm(() => {
|
|
10121
|
+
SCALAR = String.raw`(?:-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)`;
|
|
10122
|
+
SCALAR_ARRAY = new RegExp(String.raw`\[\n\s+(${SCALAR}(?:,\n\s+${SCALAR})*)\n\s*\]`, "g");
|
|
10123
|
+
});
|
|
10124
|
+
|
|
10116
10125
|
// src/resources.ts
|
|
10117
10126
|
import { readFileSync as readFileSync9, realpathSync as realpathSync3 } from "node:fs";
|
|
10118
10127
|
import { extname as extname2, resolve as resolve3 } from "node:path";
|
|
@@ -10719,10 +10728,11 @@ function inspectProject(projectPath) {
|
|
|
10719
10728
|
problems
|
|
10720
10729
|
};
|
|
10721
10730
|
}
|
|
10722
|
-
var ADDONS, EDITOR_PLUGINS, RUNTIME_AUTOLOAD, SCRIPT_RUNS_SETTING = "gdharness/runtime/serve_script_runs", BIND_ADDRESS_SETTING = "gdharness/runtime/bind_address", PORT_SETTING = "gdharness/runtime/port",
|
|
10731
|
+
var ADDONS, EDITOR_PLUGINS, RUNTIME_AUTOLOAD, SCRIPT_RUNS_SETTING = "gdharness/runtime/serve_script_runs", BIND_ADDRESS_SETTING = "gdharness/runtime/bind_address", PORT_SETTING = "gdharness/runtime/port", DIGEST_MARKER = ".gdharness-digest", RUNTIME_ADDON = "gdharness_runtime", shippedDigest, shippedRuntime;
|
|
10723
10732
|
var init_setup = __esm(() => {
|
|
10724
10733
|
init_class_cache();
|
|
10725
10734
|
init_headless();
|
|
10735
|
+
init_project_scan();
|
|
10726
10736
|
init_resources();
|
|
10727
10737
|
init_server_version();
|
|
10728
10738
|
ADDONS = ["gdharness_editor", "gdharness_runtime", "auto_reload"];
|
|
@@ -11005,10 +11015,14 @@ var init_tool_definitions = __esm(() => {
|
|
|
11005
11015
|
{
|
|
11006
11016
|
name: "project_settings",
|
|
11007
11017
|
title: "Project settings",
|
|
11008
|
-
description: "Reads or writes project.godot: settings, autoloads, the main scene, input actions, plugins and audio buses. A write with an editor open on the project is handed to the editor, which takes the settings the write changed or names from the file (named under editorAdopted), including a setting the file already held, since the editor can hold another value after the file was put back, or reloads the bus layout, so it answers the new values and does not save the old ones back over them. editorNote is an editor that could not take the write, one on an addon from before this, which still holds the old values until editor_launch restart. An enabled plugin's code still loads on the editor's next start. set answers old_value and new_value, with was_new true when project.godot did not set the setting before, and was_default true when what it held was the engine's own default, which old_value then is.",
|
|
11018
|
+
description: "Reads or writes project.godot: settings, autoloads, the main scene, input actions, plugins and audio buses. A write with an editor open on the project is handed to the editor, which takes the settings the write changed or names from the file (named under editorAdopted), including a setting the file already held, since the editor can hold another value after the file was put back, or reloads the bus layout, so it answers the new values and does not save the old ones back over them. editorNote is an editor that could not take the write, one on an addon from before this, which still holds the old values until editor_launch restart. An enabled plugin's code still loads on the editor's next start. set answers old_value and new_value, with was_new true when project.godot did not set the setting before, and was_default true when what it held was the engine's own default, which old_value then is. get answers exists, true for any setting the engine knows, and at_default, true when the value is the engine's own default and so has no line in project.godot.",
|
|
11009
11019
|
parameters: {
|
|
11010
11020
|
projectPath: PROJECT_PATH,
|
|
11011
|
-
setting: {
|
|
11021
|
+
setting: {
|
|
11022
|
+
type: "string",
|
|
11023
|
+
ops: ["get", "set"],
|
|
11024
|
+
description: 'Setting path, such as "display/window/size/viewport_width".'
|
|
11025
|
+
},
|
|
11012
11026
|
from: {
|
|
11013
11027
|
type: "string",
|
|
11014
11028
|
enum: ["disk", "editor"],
|
|
@@ -11022,40 +11036,66 @@ var init_tool_definitions = __esm(() => {
|
|
|
11022
11036
|
},
|
|
11023
11037
|
value: {
|
|
11024
11038
|
blank: true,
|
|
11039
|
+
ops: ["set"],
|
|
11025
11040
|
description: 'The value to write. Engine types may be tagged, {"_type": "Vector2", "x": 1, "y": 2}, and infinity as {"_type": "float", "value": "inf"}, the form a read answers with. "" writes an empty string.'
|
|
11026
11041
|
},
|
|
11027
|
-
name: { type: "string", description: "Autoload name." },
|
|
11028
|
-
path: {
|
|
11042
|
+
name: { type: "string", ops: ["add_autoload", "remove_autoload"], description: "Autoload name." },
|
|
11043
|
+
path: {
|
|
11044
|
+
type: "string",
|
|
11045
|
+
ops: ["add_autoload"],
|
|
11046
|
+
description: "Autoload script or scene inside the project."
|
|
11047
|
+
},
|
|
11029
11048
|
enabled: {
|
|
11030
11049
|
type: "boolean",
|
|
11031
|
-
|
|
11050
|
+
ops: ["add_autoload", "set_audio_bus_effect"],
|
|
11051
|
+
description: "add_autoload: Godot 4 loads every autoload in the list, so false is refused. Use global: false to keep the name out of the global scope, or remove_autoload to stop it loading. set_audio_bus_effect: whether the effect is on. Default true."
|
|
11032
11052
|
},
|
|
11033
11053
|
global: {
|
|
11034
11054
|
type: "boolean",
|
|
11055
|
+
ops: ["add_autoload"],
|
|
11035
11056
|
description: `Autoloads: make the name a global variable, the * in project.godot and the editor's "Global Variable" column. Default true. The autoload loads either way.`
|
|
11036
11057
|
},
|
|
11037
|
-
scenePath: SCENE_PATH,
|
|
11038
|
-
actionName: {
|
|
11039
|
-
|
|
11058
|
+
scenePath: { ...SCENE_PATH, ops: ["set_main_scene"] },
|
|
11059
|
+
actionName: {
|
|
11060
|
+
type: "string",
|
|
11061
|
+
ops: ["add_input_action", "remove_input_action"],
|
|
11062
|
+
description: 'Input action name, such as "jump".'
|
|
11063
|
+
},
|
|
11064
|
+
events: { ...INPUT_EVENTS, ops: ["add_input_action"] },
|
|
11040
11065
|
deadzone: {
|
|
11041
11066
|
type: "number",
|
|
11067
|
+
ops: ["add_input_action"],
|
|
11042
11068
|
minimum: 0,
|
|
11043
11069
|
maximum: 1,
|
|
11044
11070
|
description: "Input actions: analogue deadzone, 0 to 1. Default 0.5."
|
|
11045
11071
|
},
|
|
11046
|
-
pluginName: {
|
|
11047
|
-
|
|
11072
|
+
pluginName: {
|
|
11073
|
+
type: "string",
|
|
11074
|
+
ops: ["enable_plugin", "disable_plugin"],
|
|
11075
|
+
description: "Folder name under addons/."
|
|
11076
|
+
},
|
|
11077
|
+
busName: { type: "string", ops: ["add_audio_bus", "remove_audio_bus"], description: "Audio bus name." },
|
|
11048
11078
|
parentBusIndex: {
|
|
11049
11079
|
type: "number",
|
|
11080
|
+
ops: ["add_audio_bus"],
|
|
11050
11081
|
description: "Audio buses: the bus to send to. Default 0, Master. The new bus goes right after it, so every later bus moves one along, and the answer lists them all."
|
|
11051
11082
|
},
|
|
11052
|
-
busIndex: {
|
|
11083
|
+
busIndex: {
|
|
11084
|
+
type: "number",
|
|
11085
|
+
ops: ["set_audio_bus_effect", "set_audio_bus_volume"],
|
|
11086
|
+
description: "Audio bus index."
|
|
11087
|
+
},
|
|
11053
11088
|
effectIndex: {
|
|
11054
11089
|
type: "number",
|
|
11090
|
+
ops: ["set_audio_bus_effect"],
|
|
11055
11091
|
description: "Slot on the bus for the effect: the effect there is replaced, and one past the last adds one. Any other slot is refused."
|
|
11056
11092
|
},
|
|
11057
|
-
effectType: {
|
|
11058
|
-
|
|
11093
|
+
effectType: {
|
|
11094
|
+
type: "string",
|
|
11095
|
+
ops: ["set_audio_bus_effect"],
|
|
11096
|
+
description: 'Effect class, such as "AudioEffectReverb".'
|
|
11097
|
+
},
|
|
11098
|
+
volumeDb: { type: "number", ops: ["set_audio_bus_volume"], description: "Bus volume in decibels." }
|
|
11059
11099
|
},
|
|
11060
11100
|
requires: ["projectPath"],
|
|
11061
11101
|
operations: {
|
|
@@ -11077,9 +11117,19 @@ var init_tool_definitions = __esm(() => {
|
|
|
11077
11117
|
summary: "register an input action and its events",
|
|
11078
11118
|
requires: ["actionName", "events"]
|
|
11079
11119
|
},
|
|
11120
|
+
remove_input_action: {
|
|
11121
|
+
effect: "destructive",
|
|
11122
|
+
summary: "remove an input action the project defines",
|
|
11123
|
+
requires: ["actionName"]
|
|
11124
|
+
},
|
|
11080
11125
|
enable_plugin: { effect: "destructive", summary: "enable an addon", requires: ["pluginName"] },
|
|
11081
11126
|
disable_plugin: { effect: "destructive", summary: "disable an addon", requires: ["pluginName"] },
|
|
11082
11127
|
add_audio_bus: { effect: "additive", summary: "add an audio bus", requires: ["busName"] },
|
|
11128
|
+
remove_audio_bus: {
|
|
11129
|
+
effect: "destructive",
|
|
11130
|
+
summary: "remove an audio bus, sending what sent to it on to where it sent",
|
|
11131
|
+
requires: ["busName"]
|
|
11132
|
+
},
|
|
11083
11133
|
set_audio_bus_effect: {
|
|
11084
11134
|
effect: "destructive",
|
|
11085
11135
|
summary: "put an effect in a slot on a bus",
|
|
@@ -11096,7 +11146,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
11096
11146
|
name: "project_search",
|
|
11097
11147
|
title: "Search the project",
|
|
11098
11148
|
effect: "read",
|
|
11099
|
-
description: "Searches text or a regular expression across project files and returns file paths with line numbers. What the engine steps over is not searched: directories spelled with a dot, node_modules, and any directory holding a .gdignore. A vendored engine or an export directory is therefore absent from the results rather than matching the code you are looking for in a copy nobody runs.",
|
|
11149
|
+
description: "Searches text or a regular expression across project files and returns file paths with line numbers. What the engine steps over is not searched: directories spelled with a dot, node_modules, and any directory holding a .gdignore. A vendored engine or an export directory is therefore absent from the results rather than matching the code you are looking for in a copy nobody runs. The addons gdharness installed are not searched either, since nobody on the project wrote them.",
|
|
11100
11150
|
parameters: {
|
|
11101
11151
|
projectPath: PROJECT_PATH,
|
|
11102
11152
|
query: { type: "string", description: "The text or pattern to find." },
|
|
@@ -11258,8 +11308,18 @@ var init_tool_definitions = __esm(() => {
|
|
|
11258
11308
|
parameters: {
|
|
11259
11309
|
projectPath: PROJECT_PATH,
|
|
11260
11310
|
scenePath: SCENE_PATH,
|
|
11261
|
-
rootNodeType: {
|
|
11262
|
-
|
|
11311
|
+
rootNodeType: {
|
|
11312
|
+
type: "string",
|
|
11313
|
+
ops: ["create"],
|
|
11314
|
+
description: "create: the root node class. Default Node."
|
|
11315
|
+
},
|
|
11316
|
+
rootNodeName: {
|
|
11317
|
+
type: "string",
|
|
11318
|
+
ops: ["create"],
|
|
11319
|
+
description: "create: the root node name. Default the class name, as the editor names a new root."
|
|
11320
|
+
},
|
|
11321
|
+
script: { type: "string", ops: ["create"], description: "create: a script to attach to the root." },
|
|
11322
|
+
newPath: { type: "string", ops: ["save_as"], description: "save_as: where the copy goes." }
|
|
11263
11323
|
},
|
|
11264
11324
|
requires: ["projectPath", "scenePath"],
|
|
11265
11325
|
operations: {
|
|
@@ -11339,7 +11399,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
11339
11399
|
{
|
|
11340
11400
|
name: "scene_signal",
|
|
11341
11401
|
title: "Scene signals",
|
|
11342
|
-
description: "Signal connections in a scene file. Needs the editor connected.",
|
|
11402
|
+
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. Needs the editor connected.",
|
|
11343
11403
|
parameters: {
|
|
11344
11404
|
projectPath: PROJECT_PATH,
|
|
11345
11405
|
scenePath: SCENE_PATH,
|
|
@@ -11368,43 +11428,78 @@ var init_tool_definitions = __esm(() => {
|
|
|
11368
11428
|
{
|
|
11369
11429
|
name: "scene_animation",
|
|
11370
11430
|
title: "Animations",
|
|
11371
|
-
description: "Animations in an AnimationPlayer and states in an AnimationTree state machine. Needs the editor connected.",
|
|
11431
|
+
description: "Animations in an AnimationPlayer and states in an AnimationTree state machine. read answers with every track of an animation in the shape add_track takes, so a track read off one animation can be added to another. Needs the editor connected.",
|
|
11372
11432
|
parameters: {
|
|
11373
11433
|
projectPath: PROJECT_PATH,
|
|
11374
11434
|
scenePath: SCENE_PATH,
|
|
11375
|
-
playerNodePath: {
|
|
11435
|
+
playerNodePath: {
|
|
11436
|
+
type: "string",
|
|
11437
|
+
ops: ["read", "create", "add_track"],
|
|
11438
|
+
description: "The AnimationPlayer node."
|
|
11439
|
+
},
|
|
11376
11440
|
animationName: {
|
|
11377
11441
|
type: "string",
|
|
11378
|
-
|
|
11442
|
+
ops: ["read", "create", "add_track", "add_state"],
|
|
11443
|
+
description: "The animation in the player. read: the one to answer with whole; without it, read lists them. add_state: the one that state plays."
|
|
11379
11444
|
},
|
|
11380
|
-
length: { type: "number", description: "create: seconds. Default 1." },
|
|
11445
|
+
length: { type: "number", ops: ["create"], description: "create: seconds. Default 1." },
|
|
11381
11446
|
loopMode: {
|
|
11382
11447
|
type: "string",
|
|
11448
|
+
ops: ["create"],
|
|
11383
11449
|
enum: ["none", "linear", "pingpong"],
|
|
11384
11450
|
description: "create: default none."
|
|
11385
11451
|
},
|
|
11386
|
-
step: {
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11452
|
+
step: {
|
|
11453
|
+
type: "number",
|
|
11454
|
+
ops: ["create"],
|
|
11455
|
+
description: "create: keyframe snap in seconds. Default 0.1."
|
|
11456
|
+
},
|
|
11457
|
+
track: { ...ANIMATION_TRACK, ops: ["add_track"] },
|
|
11458
|
+
animTreePath: {
|
|
11459
|
+
type: "string",
|
|
11460
|
+
ops: ["read_states", "add_state", "connect_states"],
|
|
11461
|
+
description: "The AnimationTree node."
|
|
11462
|
+
},
|
|
11463
|
+
stateName: { type: "string", ops: ["add_state"], description: "add_state: the state to add." },
|
|
11390
11464
|
stateMachinePath: {
|
|
11391
11465
|
type: "string",
|
|
11392
|
-
|
|
11466
|
+
ops: ["read_states", "add_state", "connect_states"],
|
|
11467
|
+
description: "A nested state machine, by the names of the states that lead to it. Default the root."
|
|
11468
|
+
},
|
|
11469
|
+
fromState: {
|
|
11470
|
+
type: "string",
|
|
11471
|
+
ops: ["connect_states"],
|
|
11472
|
+
description: "connect_states: the state the transition leaves."
|
|
11473
|
+
},
|
|
11474
|
+
toState: {
|
|
11475
|
+
type: "string",
|
|
11476
|
+
ops: ["connect_states"],
|
|
11477
|
+
description: "connect_states: the state it arrives at."
|
|
11393
11478
|
},
|
|
11394
|
-
fromState: { type: "string", description: "connect_states: the state the transition leaves." },
|
|
11395
|
-
toState: { type: "string", description: "connect_states: the state it arrives at." },
|
|
11396
11479
|
transitionType: {
|
|
11397
11480
|
type: "string",
|
|
11481
|
+
ops: ["connect_states"],
|
|
11398
11482
|
enum: ["immediate", "sync", "at_end"],
|
|
11399
11483
|
description: "connect_states: default immediate."
|
|
11400
11484
|
},
|
|
11401
11485
|
advanceCondition: {
|
|
11402
11486
|
type: "string",
|
|
11487
|
+
ops: ["connect_states"],
|
|
11403
11488
|
description: "connect_states: the condition parameter that advances."
|
|
11404
11489
|
}
|
|
11405
11490
|
},
|
|
11406
11491
|
requires: ["projectPath", "scenePath"],
|
|
11407
11492
|
operations: {
|
|
11493
|
+
read: {
|
|
11494
|
+
effect: "read",
|
|
11495
|
+
summary: "the animations of an AnimationPlayer, or one with its tracks",
|
|
11496
|
+
requires: ["playerNodePath"]
|
|
11497
|
+
},
|
|
11498
|
+
read_states: {
|
|
11499
|
+
effect: "read",
|
|
11500
|
+
summary: "the states and transitions of an AnimationTree state machine",
|
|
11501
|
+
requires: ["animTreePath"]
|
|
11502
|
+
},
|
|
11408
11503
|
create: {
|
|
11409
11504
|
effect: "additive",
|
|
11410
11505
|
summary: "a new animation in an AnimationPlayer",
|
|
@@ -11508,7 +11603,11 @@ var init_tool_definitions = __esm(() => {
|
|
|
11508
11603
|
summary: "document symbols from the language server, each with its kind, the line and column of its name, and the lastLine of its declaration",
|
|
11509
11604
|
requires: []
|
|
11510
11605
|
},
|
|
11511
|
-
completion: {
|
|
11606
|
+
completion: {
|
|
11607
|
+
effect: "read",
|
|
11608
|
+
summary: "completions at a position, narrowed to the part of a name written before it, at most 100",
|
|
11609
|
+
requires: ["line", "character"]
|
|
11610
|
+
},
|
|
11512
11611
|
hover: { effect: "read", summary: "hover text at a position", requires: ["line", "character"] }
|
|
11513
11612
|
},
|
|
11514
11613
|
defaultOperation: "structure"
|
|
@@ -11531,34 +11630,59 @@ var init_tool_definitions = __esm(() => {
|
|
|
11531
11630
|
{
|
|
11532
11631
|
name: "resource_edit",
|
|
11533
11632
|
title: "Edit resources",
|
|
11534
|
-
description:
|
|
11633
|
+
description: 'Resource files: read one, create any ClassDB resource as .tres, change one, write a shader, build a TileSet, or set a Theme colour or font size. A material is a create with resourceType StandardMaterial3D, ShaderMaterial or CanvasItemMaterial. read answers with the properties the file sets, in the form modify takes, and a Theme lists its items there as "Button/colors/font_color". Needs the editor connected.',
|
|
11535
11634
|
parameters: {
|
|
11536
11635
|
projectPath: PROJECT_PATH,
|
|
11537
11636
|
resourcePath: RESOURCE_PATH,
|
|
11538
11637
|
resourceType: {
|
|
11539
11638
|
type: "string",
|
|
11639
|
+
ops: ["create"],
|
|
11540
11640
|
description: 'create: the resource class, such as "PhysicsMaterial" or "StandardMaterial3D".'
|
|
11541
11641
|
},
|
|
11542
|
-
properties: PROPERTIES,
|
|
11543
|
-
script: {
|
|
11642
|
+
properties: { ...PROPERTIES, ops: ["create", "modify"] },
|
|
11643
|
+
script: {
|
|
11644
|
+
type: "string",
|
|
11645
|
+
ops: ["create"],
|
|
11646
|
+
description: "create: a script to attach, for custom resources."
|
|
11647
|
+
},
|
|
11648
|
+
includeDefaults: {
|
|
11649
|
+
type: "boolean",
|
|
11650
|
+
ops: ["read"],
|
|
11651
|
+
description: "read: include properties still at their default. Default false."
|
|
11652
|
+
},
|
|
11544
11653
|
shaderType: {
|
|
11545
11654
|
type: "string",
|
|
11655
|
+
ops: ["create_shader"],
|
|
11546
11656
|
enum: ["canvas_item", "spatial", "particles", "sky", "fog"],
|
|
11547
11657
|
description: "create_shader."
|
|
11548
11658
|
},
|
|
11549
11659
|
code: {
|
|
11550
11660
|
type: "string",
|
|
11661
|
+
ops: ["create_shader"],
|
|
11551
11662
|
description: "create_shader: the shader source. Default: a minimal shader of that type."
|
|
11552
11663
|
},
|
|
11553
|
-
sources: TILESET_SOURCES,
|
|
11554
|
-
controlType: {
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11664
|
+
sources: { ...TILESET_SOURCES, ops: ["create_tileset"] },
|
|
11665
|
+
controlType: {
|
|
11666
|
+
type: "string",
|
|
11667
|
+
ops: ["set_theme_color", "set_theme_font_size"],
|
|
11668
|
+
description: 'Theme ops: the Control class, such as "Button".'
|
|
11669
|
+
},
|
|
11670
|
+
colorName: {
|
|
11671
|
+
type: "string",
|
|
11672
|
+
ops: ["set_theme_color"],
|
|
11673
|
+
description: 'set_theme_color: such as "font_color".'
|
|
11674
|
+
},
|
|
11675
|
+
color: { ...COLOUR, ops: ["set_theme_color"] },
|
|
11676
|
+
fontSizeName: {
|
|
11677
|
+
type: "string",
|
|
11678
|
+
ops: ["set_theme_font_size"],
|
|
11679
|
+
description: 'set_theme_font_size: such as "font_size".'
|
|
11680
|
+
},
|
|
11681
|
+
size: { type: "number", ops: ["set_theme_font_size"], description: "set_theme_font_size: pixels." }
|
|
11559
11682
|
},
|
|
11560
11683
|
requires: ["projectPath", "resourcePath"],
|
|
11561
11684
|
operations: {
|
|
11685
|
+
read: { effect: "read", summary: "the properties a resource file sets", requires: [] },
|
|
11562
11686
|
create: { effect: "destructive", summary: "a new resource of any class", requires: ["resourceType"] },
|
|
11563
11687
|
modify: {
|
|
11564
11688
|
effect: "destructive",
|
|
@@ -11585,8 +11709,8 @@ var init_tool_definitions = __esm(() => {
|
|
|
11585
11709
|
},
|
|
11586
11710
|
{
|
|
11587
11711
|
name: "editor_launch",
|
|
11588
|
-
title: "Open or
|
|
11589
|
-
description: "Opens the Godot editor on a project, or restarts the one already connected. 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.",
|
|
11712
|
+
title: "Open, restart or close the editor",
|
|
11713
|
+
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 says what that save took out of project.godot. 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.",
|
|
11590
11714
|
parameters: {
|
|
11591
11715
|
projectPath: { ...PROJECT_PATH, ops: ["open"] },
|
|
11592
11716
|
hidden: {
|
|
@@ -11602,6 +11726,11 @@ var init_tool_definitions = __esm(() => {
|
|
|
11602
11726
|
effect: "destructive",
|
|
11603
11727
|
summary: "restart the connected editor and wait for it",
|
|
11604
11728
|
requires: []
|
|
11729
|
+
},
|
|
11730
|
+
close: {
|
|
11731
|
+
effect: "destructive",
|
|
11732
|
+
summary: "save and quit the connected editor, and wait for it to go",
|
|
11733
|
+
requires: []
|
|
11605
11734
|
}
|
|
11606
11735
|
},
|
|
11607
11736
|
defaultOperation: "open"
|
|
@@ -11727,7 +11856,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
11727
11856
|
{
|
|
11728
11857
|
name: "editor_output",
|
|
11729
11858
|
title: "Game and editor output",
|
|
11730
|
-
description: "What the project started by editor_run has printed, as entries with a severity: the errors and warnings the engine reported, each with where it happened, and everything else as info. For a run the editor plays the reports come from the game itself, through the runtime addon, since the editor's debugger relays what a game prints and not what it reports; a played game without the runtime addon answers here with its prints alone, with errorsUnread true and no clean, since what it raised reaches nothing here. Answers with the counts and the verdict as well as the entries. heldAt is three answers: null for a run this server knows is not held, running or over, an object for one it knows is held at a breakpoint, whether the adapter said so or the runtime did by accepting a connection and never answering, and absent with heldUnknown beside it for a server that connected to the debugger after the stop and has no runtime to ask, since the adapter reports a stop only to the sessions connected when it happened. A run that has quit still answers here, with running false and its exit code, until the next one starts; a run ended by a signal has no exit code, and exitSignal names the signal instead. A run this server started also answers with transcript, the file both its streams are written to: uncapped, written while the run is going, and the thing to read or tail for a long run rather than the engine's own log, which every engine start rotates away. Read the file for output and this answer for state: endedBy says whether gdharness ended the run, and a transcript that has stopped growing is a run between prints rather than a run that is over. running is asked of the operating system whenever there is a process to ask about, which is every run this server started and every editor-played run whose game announced its runtime. For an editor-played run that never announced, there is no process id here and running is the editor's answer, which can lag: one measured elsewhere reported a game as playing for fifteen seconds after its process had been ended from outside. editor_status names that game under runtimes, which does not depend on the editor answering. op: \"editor\" answers about the editor itself instead, which is a different log and the only way anything here can read what an editor printed: its console reaches no plugin, so the addon cannot scrape it, and an editor gdharness opened is asked for a log file as it starts. That covers the whole session from the editor's first line, which is where the output worth reading usually is, since the class cache, the plugins and the language server all say what they have to say before any harness has connected. The answer carries the entries in the order they were printed and, beside them under repeated, each message shape several lines share: how many, what varied in each slot of it and how many different values stood there, the first occurrence, and the ordinary lines above the group, found by walking back past the group rather than by counting lines. An editor somebody opened by hand has no console here and is refused saying so rather than answered empty, because an editor that printed nothing and an editor nobody captured are not the same thing. startedAt is when the run began and elapsedMs how long it has been going; for a run that is over, endedAt is when it ended and elapsedMs how long it ran, and both are left out when nobody saw the end, as for a game closed in the editor or a run picked up from a note written before ends were recorded.",
|
|
11859
|
+
description: "What the project started by editor_run has printed, as entries with a severity: the errors and warnings the engine reported, each with where it happened, and everything else as info. For a run the editor plays the reports come from the game itself, through the runtime addon, since the editor's debugger relays what a game prints and not what it reports; a played game without the runtime addon answers here with its prints alone, with errorsUnread true and no clean, since what it raised reaches nothing here. Answers with the counts and the verdict as well as the entries: clean is true when no error was reported, and warnings, counted beside it, do not make it false. heldAt is three answers: null for a run this server knows is not held, running or over, an object for one it knows is held at a breakpoint, whether the adapter said so or the runtime did by accepting a connection and never answering, and absent with heldUnknown beside it for a server that connected to the debugger after the stop and has no runtime to ask, since the adapter reports a stop only to the sessions connected when it happened. A run that has quit still answers here, with running false and its exit code, until the next one starts; a run ended by a signal has no exit code, and exitSignal names the signal instead. A run this server started also answers with transcript, the file both its streams are written to: uncapped, written while the run is going, and the thing to read or tail for a long run rather than the engine's own log, which every engine start rotates away. Read the file for output and this answer for state: endedBy says whether gdharness ended the run, and a transcript that has stopped growing is a run between prints rather than a run that is over. running is asked of the operating system whenever there is a process to ask about, which is every run this server started and every editor-played run whose game announced its runtime. For an editor-played run that never announced, there is no process id here and running is the editor's answer, which can lag: one measured elsewhere reported a game as playing for fifteen seconds after its process had been ended from outside. editor_status names that game under runtimes, which does not depend on the editor answering. op: \"editor\" answers about the editor itself instead, which is a different log and the only way anything here can read what an editor printed: its console reaches no plugin, so the addon cannot scrape it, and an editor gdharness opened is asked for a log file as it starts. That covers the whole session from the editor's first line, which is where the output worth reading usually is, since the class cache, the plugins and the language server all say what they have to say before any harness has connected. The answer carries the entries in the order they were printed and, beside them under repeated, each message shape several lines share: how many, what varied in each slot of it and how many different values stood there, the first occurrence, and the ordinary lines above the group, found by walking back past the group rather than by counting lines. An editor somebody opened by hand has no console here and is refused saying so rather than answered empty, because an editor that printed nothing and an editor nobody captured are not the same thing. startedAt is when the run began and elapsedMs how long it has been going; for a run that is over, endedAt is when it ended and elapsedMs how long it ran, and both are left out when nobody saw the end, as for a game closed in the editor or a run picked up from a note written before ends were recorded.",
|
|
11731
11860
|
parameters: {
|
|
11732
11861
|
severity: {
|
|
11733
11862
|
type: "string",
|
|
@@ -11768,7 +11897,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
11768
11897
|
},
|
|
11769
11898
|
editor: {
|
|
11770
11899
|
effect: "read",
|
|
11771
|
-
summary: "What the connected editor itself has printed, from its first line, with repeated messages grouped and the ordinary lines above each group carried with it",
|
|
11900
|
+
summary: "What the connected editor itself has printed, from its first line, with repeated messages grouped and the ordinary lines above each group carried with it. The engine's progress bars are one line per task, saying how far an unfinished one got",
|
|
11772
11901
|
requires: []
|
|
11773
11902
|
}
|
|
11774
11903
|
},
|
|
@@ -12343,9 +12472,11 @@ var init_headless_operations = __esm(() => {
|
|
|
12343
12472
|
remove_autoload: "remove_autoload",
|
|
12344
12473
|
set_main_scene: "set_main_scene",
|
|
12345
12474
|
add_input_action: "add_input_action",
|
|
12475
|
+
remove_input_action: "remove_input_action",
|
|
12346
12476
|
enable_plugin: "enable_plugin",
|
|
12347
12477
|
disable_plugin: "disable_plugin",
|
|
12348
12478
|
add_audio_bus: "create_audio_bus",
|
|
12479
|
+
remove_audio_bus: "remove_audio_bus",
|
|
12349
12480
|
set_audio_bus_effect: "set_audio_bus_effect",
|
|
12350
12481
|
set_audio_bus_volume: "set_audio_bus_volume"
|
|
12351
12482
|
}),
|
|
@@ -12889,6 +13020,18 @@ function prefixIssues(path, issues) {
|
|
|
12889
13020
|
function unwrapMessage(message) {
|
|
12890
13021
|
return typeof message === "string" ? message : message?.message;
|
|
12891
13022
|
}
|
|
13023
|
+
function sizeCaps(defChecks) {
|
|
13024
|
+
const caps = [];
|
|
13025
|
+
for (const ch of defChecks ?? []) {
|
|
13026
|
+
const d = ch._zod.def;
|
|
13027
|
+
if (!/_(length|size)$|_equals$/.test(d.check))
|
|
13028
|
+
break;
|
|
13029
|
+
const max = d.maximum ?? d.length ?? d.size;
|
|
13030
|
+
if (max >= 0)
|
|
13031
|
+
caps.push([max, ch]);
|
|
13032
|
+
}
|
|
13033
|
+
return caps;
|
|
13034
|
+
}
|
|
12892
13035
|
function attachSchema(issues, start, inst) {
|
|
12893
13036
|
var _a;
|
|
12894
13037
|
for (let i = start;i < issues.length; i++) {
|
|
@@ -13926,7 +14069,7 @@ var init_versions = __esm(() => {
|
|
|
13926
14069
|
version = {
|
|
13927
14070
|
major: 4,
|
|
13928
14071
|
minor: 6,
|
|
13929
|
-
patch:
|
|
14072
|
+
patch: 7
|
|
13930
14073
|
};
|
|
13931
14074
|
});
|
|
13932
14075
|
|
|
@@ -14052,6 +14195,28 @@ function isValidJWT(token, algorithm = null) {
|
|
|
14052
14195
|
return false;
|
|
14053
14196
|
}
|
|
14054
14197
|
}
|
|
14198
|
+
function capSize(inst, size) {
|
|
14199
|
+
const caps = sizeCaps(inst._zod.def.checks);
|
|
14200
|
+
if (!caps.length)
|
|
14201
|
+
return;
|
|
14202
|
+
const cap = Math.min(...caps.map((c) => c[0]));
|
|
14203
|
+
const parse = inst._zod.parse;
|
|
14204
|
+
inst._zod.parse = (payload, ctx) => {
|
|
14205
|
+
const n = size(payload.value);
|
|
14206
|
+
if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
|
|
14207
|
+
for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
|
|
14208
|
+
if (n > max && ch._zod.def.when(payload)) {
|
|
14209
|
+
const start = payload.issues.length;
|
|
14210
|
+
ch._zod.check(payload);
|
|
14211
|
+
payload.issues[start].continue = false;
|
|
14212
|
+
attachSchema(payload.issues, start, inst);
|
|
14213
|
+
return payload;
|
|
14214
|
+
}
|
|
14215
|
+
}
|
|
14216
|
+
}
|
|
14217
|
+
return parse(payload, ctx);
|
|
14218
|
+
};
|
|
14219
|
+
}
|
|
14055
14220
|
function handleArrayResult(result, final, index) {
|
|
14056
14221
|
if (result.issues.length) {
|
|
14057
14222
|
final.issues.push(...prefixIssues(index, result.issues));
|
|
@@ -14357,7 +14522,7 @@ function handleRefineResult(result, payload, input, inst) {
|
|
|
14357
14522
|
payload.issues.push(issue(_iss));
|
|
14358
14523
|
}
|
|
14359
14524
|
}
|
|
14360
|
-
var $ZodType, toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value }, $ZodString, $ZodStringFormat, $ZodGUID, $ZodUUID, $ZodEmail, URL_BAD_FORMAT = 1, URL_UNPARSEABLE = 2, asciiTabOrNewline, $ZodURL, $ZodEmoji, $ZodNanoID, $ZodCUID, $ZodCUID2, $ZodULID, $ZodXID, $ZodKSUID, $ZodISODateTime, $ZodISODate, $ZodISOTime, $ZodISODuration, $ZodIPv4, ipv6Alphabet, $ZodIPv6, $ZodCIDRv4, $ZodCIDRv6, base64Charset, $ZodBase64, base64urlCharset, $ZodBase64URL, $ZodE164, $ZodJWT, $ZodNumber, $ZodNumberFormat, $ZodBoolean, $ZodNull, $ZodAny, $ZodUnknown, $ZodNever, $ZodArray, NO_SYMBOL_KEYS, $ZodObject, $ZodObjectJIT, $ZodUnion, $ZodDiscriminatedUnion, $ZodIntersection, $ZodRecord, $ZodEnum, $ZodLiteral, $ZodTransform, $ZodOptional, $ZodExactOptional, $ZodNullable, $ZodDefault, $ZodPrefault, $ZodNonOptional, $ZodCatch, $ZodPipe, $ZodPreprocess, $ZodReadonly, $ZodLazy, $ZodCustom;
|
|
14525
|
+
var $ZodType, toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value }, $ZodString, $ZodStringFormat, $ZodGUID, $ZodUUID, $ZodEmail, URL_BAD_FORMAT = 1, URL_UNPARSEABLE = 2, asciiTabOrNewline, $ZodURL, $ZodEmoji, $ZodNanoID, $ZodCUID, $ZodCUID2, $ZodULID, $ZodXID, $ZodKSUID, $ZodISODateTime, $ZodISODate, $ZodISOTime, $ZodISODuration, $ZodIPv4, ipv6Alphabet, $ZodIPv6, $ZodCIDRv4, $ZodCIDRv6, base64Charset, $ZodBase64, base64urlCharset, $ZodBase64URL, $ZodE164, $ZodJWT, $ZodNumber, $ZodNumberFormat, $ZodBoolean, $ZodNull, $ZodAny, $ZodUnknown, $ZodNever, arraySize = (input) => Array.isArray(input) ? input.length : -1, $ZodArray, NO_SYMBOL_KEYS, $ZodObject, $ZodObjectJIT, $ZodUnion, $ZodDiscriminatedUnion, $ZodIntersection, $ZodRecord, $ZodEnum, $ZodLiteral, $ZodTransform, $ZodOptional, $ZodExactOptional, $ZodNullable, $ZodDefault, $ZodPrefault, $ZodNonOptional, $ZodCatch, $ZodPipe, $ZodPreprocess, $ZodReadonly, $ZodLazy, $ZodCustom;
|
|
14361
14526
|
var init_schemas = __esm(() => {
|
|
14362
14527
|
init_checks();
|
|
14363
14528
|
init_core();
|
|
@@ -14847,6 +15012,7 @@ var init_schemas = __esm(() => {
|
|
|
14847
15012
|
}
|
|
14848
15013
|
return payload;
|
|
14849
15014
|
};
|
|
15015
|
+
capSize(inst, arraySize);
|
|
14850
15016
|
});
|
|
14851
15017
|
NO_SYMBOL_KEYS = [];
|
|
14852
15018
|
$ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
@@ -35630,10 +35796,56 @@ function editorConsole(projectPath, editorPid, openedByAServer) {
|
|
|
35630
35796
|
}
|
|
35631
35797
|
const log = new GameLog;
|
|
35632
35798
|
const { text, of } = theFirstOf(path);
|
|
35633
|
-
log.append("transcript", text);
|
|
35799
|
+
log.append("transcript", foldProgress(text));
|
|
35634
35800
|
log.finish();
|
|
35635
35801
|
return { log, path, ...of === undefined ? {} : { readBytes: text.length, of } };
|
|
35636
35802
|
}
|
|
35803
|
+
function foldProgress(text) {
|
|
35804
|
+
const out = [];
|
|
35805
|
+
const open = new Map;
|
|
35806
|
+
for (const raw of text.split(`
|
|
35807
|
+
`)) {
|
|
35808
|
+
const line = raw.replace(/\r$/, "").replace(COLOUR_CODE, "");
|
|
35809
|
+
const step = PROGRESS_STEP.exec(line);
|
|
35810
|
+
if (step !== null) {
|
|
35811
|
+
const [, percent = "", name = "", said = ""] = step;
|
|
35812
|
+
const started = /^Started (.*)$/.exec(said);
|
|
35813
|
+
if (started !== null) {
|
|
35814
|
+
const task = { name, label: started[1] ?? "", percent, done: false };
|
|
35815
|
+
open.set(name, task);
|
|
35816
|
+
out.push(task);
|
|
35817
|
+
continue;
|
|
35818
|
+
}
|
|
35819
|
+
const task = open.get(name);
|
|
35820
|
+
if (task !== undefined) {
|
|
35821
|
+
task.percent = percent;
|
|
35822
|
+
if (said.trim() !== "") {
|
|
35823
|
+
task.last = said.trim();
|
|
35824
|
+
}
|
|
35825
|
+
continue;
|
|
35826
|
+
}
|
|
35827
|
+
}
|
|
35828
|
+
const finished = PROGRESS_DONE.exec(line);
|
|
35829
|
+
const task = finished === null ? undefined : open.get(finished[1] ?? "");
|
|
35830
|
+
if (task !== undefined) {
|
|
35831
|
+
task.done = true;
|
|
35832
|
+
open.delete(task.name);
|
|
35833
|
+
continue;
|
|
35834
|
+
}
|
|
35835
|
+
out.push(raw);
|
|
35836
|
+
}
|
|
35837
|
+
return out.map((entry) => {
|
|
35838
|
+
if (typeof entry === "string") {
|
|
35839
|
+
return entry;
|
|
35840
|
+
}
|
|
35841
|
+
if (entry.done) {
|
|
35842
|
+
return `[ DONE ] ${entry.name} | ${entry.label}`;
|
|
35843
|
+
}
|
|
35844
|
+
const last = entry.last === undefined ? "" : `, and the last step it named was "${entry.last}"`;
|
|
35845
|
+
return `[ ${entry.percent}% ] ${entry.name} | ${entry.label}, which has not finished${last}`;
|
|
35846
|
+
}).join(`
|
|
35847
|
+
`);
|
|
35848
|
+
}
|
|
35637
35849
|
function theFirstOf(path) {
|
|
35638
35850
|
const whole = statSync7(path).size;
|
|
35639
35851
|
if (whole <= MOST_CONSOLE_BYTES) {
|
|
@@ -35788,9 +36000,11 @@ function linesBefore(entries, at, collapsed, wanted) {
|
|
|
35788
36000
|
}
|
|
35789
36001
|
return found.reverse();
|
|
35790
36002
|
}
|
|
35791
|
-
var MOST_CONSOLE_BYTES, NAMED_VALUES = 6, WALK_BACK_LIMIT = 500, SLOTS;
|
|
36003
|
+
var PROGRESS_STEP, PROGRESS_DONE, MOST_CONSOLE_BYTES, NAMED_VALUES = 6, WALK_BACK_LIMIT = 500, SLOTS;
|
|
35792
36004
|
var init_editor_log = __esm(() => {
|
|
35793
36005
|
init_game_log();
|
|
36006
|
+
PROGRESS_STEP = /^\[\s*(\d+)% \] (\S+) \| (.*)$/;
|
|
36007
|
+
PROGRESS_DONE = /^\[ DONE \] (\S+)\s*$/;
|
|
35794
36008
|
MOST_CONSOLE_BYTES = 8 * 1024 * 1024;
|
|
35795
36009
|
SLOTS = [/"[^"]*"/g, /'[^']*'/g, /\b(?:res|user):\/\/\S+/g, /(?<=\.gd|\.tscn|\.cs):\d+(?::\d+)?/g];
|
|
35796
36010
|
});
|
|
@@ -38739,6 +38953,12 @@ function theEditorHasComeBack(status, startedAt) {
|
|
|
38739
38953
|
function hasSaidWhoItIs(status) {
|
|
38740
38954
|
return status.connected && status.addonVersion !== undefined;
|
|
38741
38955
|
}
|
|
38956
|
+
function withoutTrailingSeparator(path) {
|
|
38957
|
+
if (path.length <= 1 || !/[\\/]$/.test(path) || /^[A-Za-z]:[\\/]$/.test(path)) {
|
|
38958
|
+
return path;
|
|
38959
|
+
}
|
|
38960
|
+
return path.slice(0, -1);
|
|
38961
|
+
}
|
|
38742
38962
|
function anEditorIsStillComing(listeningSince, launchedEditorIsAlive, now = Date.now()) {
|
|
38743
38963
|
return mayYetConnect(listeningSince, now) || launchedEditorIsAlive;
|
|
38744
38964
|
}
|
|
@@ -39048,7 +39268,7 @@ var init_godot_bridge = __esm(() => {
|
|
|
39048
39268
|
this.elsewhereUnlessOneShot(message.project_path, message.editor_pid, message.opened_by_a_server === true);
|
|
39049
39269
|
return;
|
|
39050
39270
|
}
|
|
39051
|
-
this.connectionInfo.projectPath = message.project_path;
|
|
39271
|
+
this.connectionInfo.projectPath = withoutTrailingSeparator(message.project_path);
|
|
39052
39272
|
this.connectionInfo.addonVersion = message.addon_version ?? "";
|
|
39053
39273
|
this.connectionInfo.addonDigest = message.addon_digest;
|
|
39054
39274
|
this.connectionInfo.editorPid = message.editor_pid;
|
|
@@ -40394,6 +40614,28 @@ function shownSymbol(entry) {
|
|
|
40394
40614
|
...children.length > 0 ? { children: children.map(shownSymbol) } : {}
|
|
40395
40615
|
};
|
|
40396
40616
|
}
|
|
40617
|
+
function typedBefore(content, line, character) {
|
|
40618
|
+
const text = content.split(/\r?\n/)[line] ?? "";
|
|
40619
|
+
return /[\p{L}\p{N}_]*$/u.exec(text.slice(0, character))?.[0] ?? "";
|
|
40620
|
+
}
|
|
40621
|
+
function narrowedCompletions(completions, typed) {
|
|
40622
|
+
const wanted = typed.toLowerCase();
|
|
40623
|
+
const matching = wanted === "" ? completions : completions.filter((entry) => {
|
|
40624
|
+
const record = asRecord(entry);
|
|
40625
|
+
const name = typeof record["filterText"] === "string" ? record["filterText"] : record["label"];
|
|
40626
|
+
return typeof name === "string" && name.toLowerCase().startsWith(wanted);
|
|
40627
|
+
});
|
|
40628
|
+
const shown = matching.slice(0, MOST_COMPLETIONS);
|
|
40629
|
+
return {
|
|
40630
|
+
...typed === "" ? {} : { typed },
|
|
40631
|
+
completions: shown.map(shownCompletion),
|
|
40632
|
+
total: matching.length,
|
|
40633
|
+
...matching.length > shown.length ? {
|
|
40634
|
+
omitted: matching.length - shown.length,
|
|
40635
|
+
note: `${matching.length - shown.length} more are offered here than one answer carries; ask at a position after more of the name to narrow them.`
|
|
40636
|
+
} : {}
|
|
40637
|
+
};
|
|
40638
|
+
}
|
|
40397
40639
|
function shownCompletion(entry) {
|
|
40398
40640
|
const { data: _request, kind, ...rest } = asRecord(entry);
|
|
40399
40641
|
return { ...rest, kind: named(kind, COMPLETION_KINDS) };
|
|
@@ -40464,7 +40706,7 @@ async function handleLSPTool(client, toolName, args) {
|
|
|
40464
40706
|
case "lsp_get_completions": {
|
|
40465
40707
|
const { line, character } = protocolPosition(parsedArgs);
|
|
40466
40708
|
const completions = await client.getCompletions(scriptPath, content, line, character);
|
|
40467
|
-
return asToolResponse(
|
|
40709
|
+
return asToolResponse(narrowedCompletions(completions, typedBefore(content, line, character)));
|
|
40468
40710
|
}
|
|
40469
40711
|
case "lsp_get_hover": {
|
|
40470
40712
|
const { line, character } = protocolPosition(parsedArgs);
|
|
@@ -40489,7 +40731,7 @@ async function handleLSPTool(client, toolName, args) {
|
|
|
40489
40731
|
});
|
|
40490
40732
|
}
|
|
40491
40733
|
}
|
|
40492
|
-
var DEFAULT_LSP_PORT = 6005, DIAGNOSTICS_TIMEOUT_MS = 5000, REQUEST_TIMEOUT_MS2 = 1e4, REFERENCES_TIMEOUT_MS = 180000, LSPTimeout, LANGUAGE_SERVER_START_MS = 30000, LANGUAGE_SERVER_RETRY_MS = 250, LanguageServerNotListening, ArgumentRefusal, NoDiagnosticsPublished, AnotherProjectsServer, SEVERITIES, SYMBOL_KINDS, COMPLETION_KINDS;
|
|
40734
|
+
var DEFAULT_LSP_PORT = 6005, DIAGNOSTICS_TIMEOUT_MS = 5000, REQUEST_TIMEOUT_MS2 = 1e4, REFERENCES_TIMEOUT_MS = 180000, LSPTimeout, LANGUAGE_SERVER_START_MS = 30000, LANGUAGE_SERVER_RETRY_MS = 250, LanguageServerNotListening, ArgumentRefusal, NoDiagnosticsPublished, AnotherProjectsServer, SEVERITIES, SYMBOL_KINDS, COMPLETION_KINDS, MOST_COMPLETIONS = 100;
|
|
40493
40735
|
var init_lsp_client = __esm(() => {
|
|
40494
40736
|
init_answer_json();
|
|
40495
40737
|
init_errors();
|
|
@@ -40799,7 +41041,11 @@ var init_prompts = __esm(() => {
|
|
|
40799
41041
|
}
|
|
40800
41042
|
],
|
|
40801
41043
|
steps: [
|
|
40802
|
-
{
|
|
41044
|
+
{
|
|
41045
|
+
tool: "editor_status",
|
|
41046
|
+
passes: [],
|
|
41047
|
+
why: "see whether an editor is connected and its addon matches; without one the run is a game of its own, not a fault"
|
|
41048
|
+
},
|
|
40803
41049
|
{ tool: "editor_run", op: "start", passes: ["projectPath", "scene"], why: "start the run" },
|
|
40804
41050
|
{
|
|
40805
41051
|
tool: "editor_run",
|
|
@@ -40817,7 +41063,11 @@ var init_prompts = __esm(() => {
|
|
|
40817
41063
|
description: "Check the editor connection, the project health report, export validation and the import state.",
|
|
40818
41064
|
arguments: [PROJECT_PATH2],
|
|
40819
41065
|
steps: [
|
|
40820
|
-
{
|
|
41066
|
+
{
|
|
41067
|
+
tool: "editor_status",
|
|
41068
|
+
passes: [],
|
|
41069
|
+
why: "see whether an editor is connected and, if one is, whether its addon matches; no editor is no fault in the project, so leave it out of what is wrong"
|
|
41070
|
+
},
|
|
40821
41071
|
{
|
|
40822
41072
|
tool: "project_info",
|
|
40823
41073
|
passes: ["projectPath"],
|
|
@@ -43376,6 +43626,7 @@ function settingsNamedBy(op, args) {
|
|
|
43376
43626
|
case "set_main_scene":
|
|
43377
43627
|
return ["application/run/main_scene"];
|
|
43378
43628
|
case "add_input_action":
|
|
43629
|
+
case "remove_input_action":
|
|
43379
43630
|
return text("actionName") === "" ? [] : [`input/${text("actionName")}`];
|
|
43380
43631
|
case "enable_plugin":
|
|
43381
43632
|
case "disable_plugin":
|
|
@@ -43931,6 +44182,7 @@ class GodotServer {
|
|
|
43931
44182
|
launchedEditor = null;
|
|
43932
44183
|
launchedFrom = null;
|
|
43933
44184
|
launchedDropped = null;
|
|
44185
|
+
closedHere = null;
|
|
43934
44186
|
ownProject;
|
|
43935
44187
|
announcedAt = null;
|
|
43936
44188
|
handingOverFrom = null;
|
|
@@ -43940,6 +44192,7 @@ class GodotServer {
|
|
|
43940
44192
|
this.godotBridge = getDefaultBridge(this.ownProject);
|
|
43941
44193
|
this.godotBridge.identifyEditorsWith(oneShotOptionOf);
|
|
43942
44194
|
this.godotBridge.on("godot_connected", () => {
|
|
44195
|
+
this.closedHere = null;
|
|
43943
44196
|
this.settleTheLaunchReading();
|
|
43944
44197
|
});
|
|
43945
44198
|
this.setupShutdownHandlers();
|
|
@@ -44533,6 +44786,10 @@ class GodotServer {
|
|
|
44533
44786
|
}
|
|
44534
44787
|
case "scene_animation":
|
|
44535
44788
|
switch (op) {
|
|
44789
|
+
case "read":
|
|
44790
|
+
return await bridge("read_animations");
|
|
44791
|
+
case "read_states":
|
|
44792
|
+
return await bridge("read_animation_states");
|
|
44536
44793
|
case "create":
|
|
44537
44794
|
return await bridge("create_animation");
|
|
44538
44795
|
case "add_track":
|
|
@@ -44557,6 +44814,8 @@ class GodotServer {
|
|
|
44557
44814
|
return await this.handleScriptDiagnostics(args);
|
|
44558
44815
|
case "resource_edit":
|
|
44559
44816
|
switch (op) {
|
|
44817
|
+
case "read":
|
|
44818
|
+
return await bridge("read_resource");
|
|
44560
44819
|
case "create":
|
|
44561
44820
|
return await bridge("create_resource");
|
|
44562
44821
|
case "modify":
|
|
@@ -44571,6 +44830,9 @@ class GodotServer {
|
|
|
44571
44830
|
return await bridge("set_theme_font_size", { themePath: args["resourcePath"] });
|
|
44572
44831
|
}
|
|
44573
44832
|
case "editor_launch":
|
|
44833
|
+
if (op === "close") {
|
|
44834
|
+
return await this.handleCloseEditor();
|
|
44835
|
+
}
|
|
44574
44836
|
return op === "restart" ? await this.handleRestartEditor(args) : await this.handleLaunchEditor(args);
|
|
44575
44837
|
case "editor_run":
|
|
44576
44838
|
if (op === "stop") {
|
|
@@ -45468,21 +45730,31 @@ class GodotServer {
|
|
|
45468
45730
|
}
|
|
45469
45731
|
const missing = paths.value.filter((path) => !existsSync20(join26(project.value.path, path.slice("res://".length))));
|
|
45470
45732
|
const asked = paths.value.filter((path) => !missing.includes(path));
|
|
45733
|
+
const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
|
|
45734
|
+
const noRunner = !existsSync20(join26(project.value.path, runner));
|
|
45471
45735
|
if (asked.length === 0) {
|
|
45472
45736
|
const verdict = `nothing at ${missing.join(" and ")}`;
|
|
45737
|
+
const andNoRunner = noRunner ? `, and gdUnit4 is not installed in this project: no ${runner}` : "";
|
|
45473
45738
|
return {
|
|
45474
45739
|
content: [
|
|
45475
45740
|
{
|
|
45476
45741
|
type: "text",
|
|
45477
|
-
text: `No tests ran: ${verdict}.${elsewhereIn(project.value.path, missing[0] ?? "")}`
|
|
45742
|
+
text: `No tests ran: ${verdict}${andNoRunner}.${elsewhereIn(project.value.path, missing[0] ?? "")}`
|
|
45478
45743
|
},
|
|
45479
|
-
{
|
|
45744
|
+
{
|
|
45745
|
+
type: "text",
|
|
45746
|
+
text: answerJson({
|
|
45747
|
+
passed: false,
|
|
45748
|
+
verdict,
|
|
45749
|
+
tests: 0,
|
|
45750
|
+
...noRunner ? { gdUnit4Installed: false } : {}
|
|
45751
|
+
})
|
|
45752
|
+
}
|
|
45480
45753
|
],
|
|
45481
45754
|
isError: true
|
|
45482
45755
|
};
|
|
45483
45756
|
}
|
|
45484
|
-
|
|
45485
|
-
if (!existsSync20(join26(project.value.path, runner))) {
|
|
45757
|
+
if (noRunner) {
|
|
45486
45758
|
return this.createErrorResponse(`gdUnit4 is not installed in this project: no ${runner}.`, [
|
|
45487
45759
|
"Install gdUnit4 under addons/gdUnit4, from https://github.com/godot-gdunit-labs/gdUnit4"
|
|
45488
45760
|
]);
|
|
@@ -46065,8 +46337,12 @@ class GodotServer {
|
|
|
46065
46337
|
addonIsStale: greeted ? stale : undefined,
|
|
46066
46338
|
greeting: status.connected && !greeted ? "The editor has connected and has not yet said who it is: its project, pid, addon version and ports arrive with its greeting a moment after the socket opens, later while it imports. Ask again for them." : undefined,
|
|
46067
46339
|
bridgeAvailable: this.bridgeStartupError === null && status.port !== null,
|
|
46068
|
-
mayYetConnect: status.connected ? undefined : arriving.length > 0 ? true : unfinished !== null ? unfinished.underway : anEditorIsStillComing(status.listeningSince, launchedIsUp),
|
|
46340
|
+
mayYetConnect: status.connected ? undefined : arriving.length > 0 ? true : unfinished !== null ? unfinished.underway : this.closedHere !== null ? false : anEditorIsStillComing(status.listeningSince, launchedIsUp),
|
|
46069
46341
|
editorsNotYetConnected: arriving.length > 0 ? arriving : undefined,
|
|
46342
|
+
closedHere: status.connected || arriving.length > 0 || this.closedHere === null ? undefined : {
|
|
46343
|
+
...this.closedHere,
|
|
46344
|
+
note: "This server closed the editor on request, so nothing is coming until editor_launch open starts one."
|
|
46345
|
+
},
|
|
46070
46346
|
restartInterrupted: unfinished === null || unfinished.underway || arriving.length > 0 ? undefined : {
|
|
46071
46347
|
quitEditorPid: unfinished.note.editorPid,
|
|
46072
46348
|
quitAt: unfinished.note.quitAt,
|
|
@@ -46311,6 +46587,42 @@ class GodotServer {
|
|
|
46311
46587
|
tookMs: Date.now() - began
|
|
46312
46588
|
});
|
|
46313
46589
|
}
|
|
46590
|
+
async handleCloseEditor() {
|
|
46591
|
+
const before = this.godotBridge.getStatus();
|
|
46592
|
+
if (!before.connected) {
|
|
46593
|
+
return this.createErrorResponse("No editor is connected, so there is nothing to close.", [
|
|
46594
|
+
"editor_status says whether the bridge is up and what has reached it"
|
|
46595
|
+
]);
|
|
46596
|
+
}
|
|
46597
|
+
if (!hasSaidWhoItIs(before) || before.editorPid === undefined) {
|
|
46598
|
+
return this.createErrorResponse(`The editor has connected and has not said who it is within ${greetingWaitMs() / 1000}s, so there is no process to wait on once it is asked to go.`, ["editor_status says when it has, under greeting while it has not", "Then ask for the close again"]);
|
|
46599
|
+
}
|
|
46600
|
+
const pid = before.editorPid;
|
|
46601
|
+
const settingsBefore = this.settingKeysOf(before.projectPath);
|
|
46602
|
+
const asked = await this.handleViaBridge("quit_editor", {});
|
|
46603
|
+
if (asked.isError === true) {
|
|
46604
|
+
return asked;
|
|
46605
|
+
}
|
|
46606
|
+
const began = Date.now();
|
|
46607
|
+
const gone = await this.waitForBridge(() => !alive(pid), began + editorRestartTimeoutMs());
|
|
46608
|
+
if (!gone) {
|
|
46609
|
+
return this.createErrorResponse(`The editor saved and was asked to go, and pid ${pid} is still running after ${editorRestartTimeoutMs() / 1000}s.`, [
|
|
46610
|
+
"It may be asking what to do about unsaved changes, or a script may be holding up its exit",
|
|
46611
|
+
"editor_status says whether it is still connected"
|
|
46612
|
+
]);
|
|
46613
|
+
}
|
|
46614
|
+
this.closedHere = { editorPid: pid, at: new Date().toISOString() };
|
|
46615
|
+
if (this.launchedEditor?.pid === pid) {
|
|
46616
|
+
this.launchedEditor = null;
|
|
46617
|
+
}
|
|
46618
|
+
return this.jsonTextResponse({
|
|
46619
|
+
closed: true,
|
|
46620
|
+
editorPid: pid,
|
|
46621
|
+
projectPath: before.projectPath,
|
|
46622
|
+
...this.whatTheEditorDropped(settingsBefore, this.settingKeysOf(before.projectPath)),
|
|
46623
|
+
tookMs: Date.now() - began
|
|
46624
|
+
});
|
|
46625
|
+
}
|
|
46314
46626
|
settleTheLaunchReading() {
|
|
46315
46627
|
const watched = this.launchedFrom;
|
|
46316
46628
|
const status = this.godotBridge.getStatus();
|
|
@@ -46482,6 +46794,7 @@ class GodotServer {
|
|
|
46482
46794
|
pid: launched.pid,
|
|
46483
46795
|
startedAt: (await startTimesOf([launched.pid])).get(launched.pid) ?? null
|
|
46484
46796
|
};
|
|
46797
|
+
this.closedHere = null;
|
|
46485
46798
|
return { pid: launched.pid, error: null };
|
|
46486
46799
|
}
|
|
46487
46800
|
async portsForAnEditor() {
|
|
@@ -46727,7 +47040,7 @@ class GodotServer {
|
|
|
46727
47040
|
frameFunctions: profileFrameFunctions(projectPath)
|
|
46728
47041
|
});
|
|
46729
47042
|
if (armed.isError === true) {
|
|
46730
|
-
return
|
|
47043
|
+
return armed;
|
|
46731
47044
|
}
|
|
46732
47045
|
}
|
|
46733
47046
|
const answer = await this.handleViaBridge("play_scene", scene === null ? {} : { scenePath: `res://${scene}` });
|
|
@@ -47577,7 +47890,7 @@ class GodotServer {
|
|
|
47577
47890
|
async profileOfThePlayedGame(going, projectPath, fromProject, limit) {
|
|
47578
47891
|
const read = await this.handleViaBridge("profile_read", {});
|
|
47579
47892
|
if (read.isError === true) {
|
|
47580
|
-
return
|
|
47893
|
+
return read;
|
|
47581
47894
|
}
|
|
47582
47895
|
const held = asParams(JSON.parse(read.content[0]?.text ?? "{}"));
|
|
47583
47896
|
if (readBoolean(held, "profiled") !== true && readBoolean(held, "armed") !== true) {
|
|
@@ -47590,7 +47903,7 @@ class GodotServer {
|
|
|
47590
47903
|
frameFunctions: profileFrameFunctions(projectPath)
|
|
47591
47904
|
});
|
|
47592
47905
|
if (started.isError === true) {
|
|
47593
|
-
return
|
|
47906
|
+
return started;
|
|
47594
47907
|
}
|
|
47595
47908
|
if (readBoolean(asParams(JSON.parse(started.content[0]?.text ?? "{}")), "started") !== true) {
|
|
47596
47909
|
return this.createErrorResponse("The editor says it is playing and has no debugger session for the game, so there is nothing to switch the profiler on in yet.", ["Ask again in a moment, once the game is up"]);
|
|
@@ -47646,13 +47959,6 @@ class GodotServer {
|
|
|
47646
47959
|
}
|
|
47647
47960
|
return false;
|
|
47648
47961
|
}
|
|
47649
|
-
profilerRefusal(refused) {
|
|
47650
|
-
const said = refused.content[0]?.text ?? "";
|
|
47651
|
-
return said.includes("Unknown tool: profile_") ? this.createErrorResponse("The editor's gdharness addon is older than the profiler, so it cannot profile the game it plays.", [
|
|
47652
|
-
"editor_launch restart loads the addon this server installed",
|
|
47653
|
-
"editor_status says which addon the editor holds"
|
|
47654
|
-
]) : refused;
|
|
47655
|
-
}
|
|
47656
47962
|
async handleWaitForRun(args) {
|
|
47657
47963
|
await this.pickUpWhatTheEditorIsPlaying();
|
|
47658
47964
|
const run = await this.currentRun();
|
|
@@ -48616,7 +48922,13 @@ class GodotServer {
|
|
|
48616
48922
|
try {
|
|
48617
48923
|
return this.jsonTextResponse(markIfStale(await this.godotBridge.invokeTool(toolName, args), this.godotBridge.getStatus().addonVersion, SERVER_VERSION, this.godotBridge.getStatus().addonDigest, shippedEditorDigest(), this.editorCodeOnDisk()));
|
|
48618
48924
|
} catch (error) {
|
|
48619
|
-
|
|
48925
|
+
const message = errorMessage(error);
|
|
48926
|
+
if (message.includes(`Unknown tool: ${toolName}`)) {
|
|
48927
|
+
const status = this.godotBridge.getStatus();
|
|
48928
|
+
const remedy = addonMismatch(status.addonVersion, SERVER_VERSION, status.addonDigest, shippedEditorDigest(), this.editorCodeOnDisk());
|
|
48929
|
+
return this.createErrorResponse(`The editor's gdharness addon is older than this ${SERVER_VERSION} server and has no ${toolName}, so it cannot answer this call. ${remedy ?? "Restart it with editor_launch restart to load the addon the project holds."}`, ["editor_status says which addon the editor holds"]);
|
|
48930
|
+
}
|
|
48931
|
+
return this.createErrorResponse(`The editor answered ${toolName} with an error: ${message}`);
|
|
48620
48932
|
}
|
|
48621
48933
|
}
|
|
48622
48934
|
runtimeTimeoutMs() {
|
|
@@ -48971,6 +49283,7 @@ var init_server = __esm(() => {
|
|
|
48971
49283
|
HANDOVER_MS = SUCCESSOR_CHECK_MS + 5000;
|
|
48972
49284
|
AUDIO_BUS_OPS = new Set([
|
|
48973
49285
|
"add_audio_bus",
|
|
49286
|
+
"remove_audio_bus",
|
|
48974
49287
|
"set_audio_bus_effect",
|
|
48975
49288
|
"set_audio_bus_volume"
|
|
48976
49289
|
]);
|