gdharness 1.2.25 → 1.2.26
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 +82 -16
- package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +290 -0
- package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +7 -0
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +150 -0
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +5 -0
- package/build/godot/operations/import_pipeline.gd +92 -0
- package/build/godot/operations/input_actions.gd +3 -2
- package/build/godot/operations/plugins.gd +3 -2
- package/build/godot/operations/project_config.gd +17 -9
- package/build/godot/operations/project_file.gd +202 -0
- package/build/index.js +82 -16
- package/build/keeper.js +4 -1
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -24933,12 +24933,27 @@ var ENGINE_FLAGS = Object.freeze({
|
|
|
24933
24933
|
"--fixed-fps": "number",
|
|
24934
24934
|
"--max-fps": "number",
|
|
24935
24935
|
"--resolution": "size",
|
|
24936
|
-
"--write-movie": "file"
|
|
24936
|
+
"--write-movie": "file",
|
|
24937
|
+
"--rendering-driver": "driver",
|
|
24938
|
+
"--rendering-method": "method",
|
|
24939
|
+
"--accessibility": "accessibility"
|
|
24937
24940
|
});
|
|
24938
24941
|
var VALUE_KIND = {
|
|
24939
24942
|
number: { pattern: /^\d+(?:\.\d+)?$/, named: "a number" },
|
|
24940
24943
|
size: { pattern: /^\d+x\d+$/, named: "a size such as 1280x720" },
|
|
24941
|
-
file: { pattern: /^[^-]/, named: "a file path" }
|
|
24944
|
+
file: { pattern: /^[^-]/, named: "a file path" },
|
|
24945
|
+
driver: {
|
|
24946
|
+
pattern: /^(?:vulkan|d3d12|metal|opengl3|opengl3_es|opengl3_angle|dummy)$/,
|
|
24947
|
+
named: "a rendering driver: vulkan, d3d12, metal, opengl3, opengl3_es, opengl3_angle or dummy"
|
|
24948
|
+
},
|
|
24949
|
+
method: {
|
|
24950
|
+
pattern: /^(?:forward_plus|mobile|gl_compatibility)$/,
|
|
24951
|
+
named: "a rendering method: forward_plus, mobile or gl_compatibility"
|
|
24952
|
+
},
|
|
24953
|
+
accessibility: {
|
|
24954
|
+
pattern: /^(?:auto|always|disabled)$/,
|
|
24955
|
+
named: "an accessibility mode: auto, always or disabled"
|
|
24956
|
+
}
|
|
24942
24957
|
};
|
|
24943
24958
|
var SET_BY_ARGUMENT = Object.freeze({
|
|
24944
24959
|
"--headless": "headless",
|
|
@@ -24954,7 +24969,7 @@ function engineFlags(given) {
|
|
|
24954
24969
|
const setBy = Object.hasOwn(SET_BY_ARGUMENT, flag) ? SET_BY_ARGUMENT[flag] : undefined;
|
|
24955
24970
|
return {
|
|
24956
24971
|
ok: false,
|
|
24957
|
-
reason: setBy !== undefined ? `${flag} is set by this tool's own argument, ${setBy}, rather than through engineArgs.` : `${flag} is not one of the engine flags engineArgs takes, which are those that change what the engine logs, draws for debugging, checks on the GPU
|
|
24972
|
+
reason: setBy !== undefined ? `${flag} is set by this tool's own argument, ${setBy}, rather than through engineArgs.` : `${flag} is not one of the engine flags engineArgs takes, which are those that change what the engine logs, draws for debugging, checks on the GPU, which renderer draws, how it times frames or whether it builds the tree a screen reader reads, and Movie Maker's --write-movie: ${offered}. A value goes as the next entry, as in ["--fixed-fps", "60"].`
|
|
24958
24973
|
};
|
|
24959
24974
|
}
|
|
24960
24975
|
if (takes === "none") {
|
|
@@ -29643,7 +29658,7 @@ function reported2(problems) {
|
|
|
29643
29658
|
return omitted === 0 ? { messages: problems } : { messages: problems.slice(omitted), messagesOmitted: omitted };
|
|
29644
29659
|
}
|
|
29645
29660
|
function reason(log, problems) {
|
|
29646
|
-
const own = log
|
|
29661
|
+
const own = refusalsIn(log);
|
|
29647
29662
|
if (own.length > 0) {
|
|
29648
29663
|
return own.map((entry) => entry.text.slice(OWN_ERROR.length)).join("; ");
|
|
29649
29664
|
}
|
|
@@ -29655,6 +29670,9 @@ function reason(log, problems) {
|
|
|
29655
29670
|
const printed = log.everything().filter((entry) => entry.source === "stdout");
|
|
29656
29671
|
return printed.at(-1)?.text ?? "no output at all";
|
|
29657
29672
|
}
|
|
29673
|
+
function refusalsIn(log) {
|
|
29674
|
+
return log.everything().filter((entry) => entry.source === "stderr" && entry.severity === "info" && entry.text.startsWith(OWN_ERROR));
|
|
29675
|
+
}
|
|
29658
29676
|
function scriptFault(problems, script) {
|
|
29659
29677
|
const spelled = (path) => `(${path.replaceAll("\\", "/").toLowerCase()}/`;
|
|
29660
29678
|
const directories = [...new Set([spelled(dirname8(script)), spelled(resolvedOr(dirname8(script)))])];
|
|
@@ -29774,6 +29792,15 @@ async function runOperation(engine, operation, params, projectPath) {
|
|
|
29774
29792
|
};
|
|
29775
29793
|
}
|
|
29776
29794
|
if (answer.kind === "none") {
|
|
29795
|
+
const refusals = refusalsIn(ran.log);
|
|
29796
|
+
if (refusals.length > 0) {
|
|
29797
|
+
const said = new Set(refusals.map((entry) => entry.index));
|
|
29798
|
+
return {
|
|
29799
|
+
ok: false,
|
|
29800
|
+
message: refusals.map((entry) => entry.text.slice(OWN_ERROR.length)).join("; "),
|
|
29801
|
+
...reported2(problems.filter((entry) => !said.has(entry.index)))
|
|
29802
|
+
};
|
|
29803
|
+
}
|
|
29777
29804
|
const ending = ran.exitCode === 0 && ran.failure === null ? "produced no result" : `failed (${howItEnded(ran)})`;
|
|
29778
29805
|
return {
|
|
29779
29806
|
ok: false,
|
|
@@ -34221,7 +34248,7 @@ var TOOL_SPECS = [
|
|
|
34221
34248
|
{
|
|
34222
34249
|
name: "project_settings",
|
|
34223
34250
|
title: "Project settings",
|
|
34224
|
-
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. Each setting under prefix carries at_default too, so a family read separates what the project sets from the engine's defaults; it is absent for a setting the engine registers no default for, such as an input action the project added, which only the project can have set.",
|
|
34251
|
+
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. A set of the value the setting already holds, in the same type, writes nothing and answers unchanged true and saved false. Every write keeps the sections and keys of project.godot in the order the file had them, so a change touches only its own lines. 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. Each setting under prefix carries at_default too, so a family read separates what the project sets from the engine's defaults; it is absent for a setting the engine registers no default for, such as an input action the project added, which only the project can have set.",
|
|
34225
34252
|
parameters: {
|
|
34226
34253
|
projectPath: PROJECT_PATH2,
|
|
34227
34254
|
setting: {
|
|
@@ -34406,7 +34433,7 @@ var TOOL_SPECS = [
|
|
|
34406
34433
|
},
|
|
34407
34434
|
options: {
|
|
34408
34435
|
type: "object",
|
|
34409
|
-
description:
|
|
34436
|
+
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.`,
|
|
34410
34437
|
additionalProperties: true
|
|
34411
34438
|
},
|
|
34412
34439
|
reimport: {
|
|
@@ -34494,7 +34521,7 @@ var TOOL_SPECS = [
|
|
|
34494
34521
|
engineArgs: {
|
|
34495
34522
|
type: "array",
|
|
34496
34523
|
items: { type: "string" },
|
|
34497
|
-
description: `The engine's own flags for the run, such as ["--verbose"], a value going as the next entry. Only those that change what the engine logs, draws for debugging, checks on the GPU
|
|
34524
|
+
description: `The engine's own flags for the run, such as ["--verbose"], a value going as the next entry. Only those that change what the engine logs, draws for debugging, checks on the GPU, which renderer draws, how it times frames or whether it builds the tree a screen reader reads: ${Object.keys(ENGINE_FLAGS).join(", ")}. Any other is refused. With --verbose, engineEntries holds the ordinary lines the run printed as well, which is where the engine names the instances leaked and the resources still in use at exit.`
|
|
34498
34525
|
},
|
|
34499
34526
|
failFast: {
|
|
34500
34527
|
type: "boolean",
|
|
@@ -34971,7 +34998,7 @@ var TOOL_SPECS = [
|
|
|
34971
34998
|
type: "array",
|
|
34972
34999
|
items: { type: "string" },
|
|
34973
35000
|
ops: ["start", "check"],
|
|
34974
|
-
description: `The engine's own flags, before the separator, such as ["--verbose"] or ["--fixed-fps", "60"], a value going as the next entry. Only those that change what the engine logs, draws for debugging, checks on the GPU
|
|
35001
|
+
description: `The engine's own flags, before the separator, such as ["--verbose"] or ["--fixed-fps", "60"], a value going as the next entry. Only those that change what the engine logs, draws for debugging, checks on the GPU, which renderer draws, how it times frames or whether it builds the tree a screen reader reads, and Movie Maker's --write-movie: ${Object.keys(ENGINE_FLAGS).join(", ")}. Any other is refused, since the engine's command line can also run scripts, open other projects and write files. --rendering-driver takes vulkan, d3d12, metal, opengl3, opengl3_es, opengl3_angle or dummy, and --rendering-method forward_plus, mobile or gl_compatibility, so the same scene can be measured on another driver and a project's OpenGL fallback exercised on a machine that has Vulkan; they choose what draws a run with a window. --accessibility always has the game build the tree a screen reader reads, as the project's accessibility/general/accessibility_support at Always Active does, so runtime_inspect accessibility can read it; otherwise the engine builds it only when a screen reader is running. --write-movie takes an absolute path outside the project, in a directory that exists, ending in .avi (one file, video and sound) or .png (one numbered PNG per frame and a .wav beside them), where nothing it would write is there already; it needs a start with headless: false, since the engine crashes writing a movie headless, and it records at the project's editor/movie_writer/fps unless --fixed-fps says otherwise. A run with any is started by this server, as one with args is. A check given --verbose answers with everything printed rather than only errors and warnings, since what verbose adds, the instances leaked at exit among it, is printed as ordinary lines.`
|
|
34975
35002
|
},
|
|
34976
35003
|
headless: { type: "boolean", ops: ["start"], description: "start: force a window or no window." },
|
|
34977
35004
|
visible: {
|
|
@@ -35211,7 +35238,7 @@ var TOOL_SPECS = [
|
|
|
35211
35238
|
{
|
|
35212
35239
|
name: "runtime_inspect",
|
|
35213
35240
|
title: "Inspect the running game",
|
|
35214
|
-
description: "Questions about the running game: what is written on the screen, the scene tree, the nodes matching a query, where one node is on screen, what one property reads,
|
|
35241
|
+
description: "Questions about the running game: what is written on the screen, the scene tree, the nodes matching a query, where one node is on screen, what one property reads, the performance metrics, or what it tells a screen reader. Needs the game running with the runtime addon.",
|
|
35215
35242
|
parameters: {
|
|
35216
35243
|
projectPath: RUNNING_PROJECT_PATH,
|
|
35217
35244
|
pid: RUNNING_PID,
|
|
@@ -35280,7 +35307,7 @@ var TOOL_SPECS = [
|
|
|
35280
35307
|
timeoutMs: {
|
|
35281
35308
|
type: "integer",
|
|
35282
35309
|
minimum: 1,
|
|
35283
|
-
description: "How long to wait for the answer before answering pending with a requestId, which runtime_invoke op result collects the reply by. Default 10000, or GDHARNESS_RUNTIME_TIMEOUT_MS."
|
|
35310
|
+
description: "How long to wait for the answer before answering pending with a requestId, which runtime_invoke op result collects the reply by. Default 10000, or GDHARNESS_RUNTIME_TIMEOUT_MS; accessibility defaults to 30000 or that, whichever is longer."
|
|
35284
35311
|
}
|
|
35285
35312
|
},
|
|
35286
35313
|
requires: [],
|
|
@@ -35308,7 +35335,12 @@ var TOOL_SPECS = [
|
|
|
35308
35335
|
},
|
|
35309
35336
|
metrics: {
|
|
35310
35337
|
effect: "read",
|
|
35311
|
-
summary: "frame time, memory, draw calls and the rest. frame_time is the mean wall time of a frame over the last frames_timed frames (up to 120, timed by the game itself, physics and the wait for the display included), frame_time_max the slowest of them, both in seconds and null before a frame has passed; vsync says whether a frame waits for the display, and max_fps is the game's frame-rate cap, 0 for none. fps, process_time_max and physics_time are the engine's monitors, which it sets once a second: the frames counted in the last second, and the slowest process and physics step in it, so they trail a change by up to a second and the last two are a worst case rather than the frame. The memory, object and render counts are read as asked",
|
|
35338
|
+
summary: "frame time, memory, draw calls and the rest. frame_time is the mean wall time of a frame over the last frames_timed frames (up to 120, timed by the game itself, physics and the wait for the display included), frame_time_max the slowest of them, both in seconds and null before a frame has passed; vsync says whether a frame waits for the display, and max_fps is the game's frame-rate cap, 0 for none. fps, process_time_max and physics_time are the engine's monitors, which it sets once a second: the frames counted in the last second, and the slowest process and physics step in it, so they trail a change by up to a second and the last two are a worst case rather than the frame. The memory, object and render counts are read as asked. memory_static is what the engine allocated on the CPU side, in bytes; render_video_mem_used, render_texture_mem_used and render_buffer_mem_used are what the renderer has on the GPU, in bytes, which memory_static does not count",
|
|
35339
|
+
requires: []
|
|
35340
|
+
},
|
|
35341
|
+
accessibility: {
|
|
35342
|
+
effect: "read",
|
|
35343
|
+
summary: `what the game tells a screen reader, read through UI Automation as a Windows screen reader reads it, under windows: one tree per window, each element with its role as UI Automation names it (text for static text, button, check_box, group for a control holding others), its name, its value where it has one, its bounds in the window's pixels, the actions a screen reader is offered (click, focus, toggle, set_value, select, expand_collapse, scroll_into_view), and focused on the one holding the focus. The name is what is read aloud, so an empty one is read as nothing; static text takes it from DisplayServer.accessibility_update_set_value, not from a name set on it, and the answer says under _note how many text elements on screen have none. With no control focused, the engine reports the first node under the root as focused, which in a run with the runtime is GdharnessRuntime. Needs a windowed run on Windows started with engineArgs ["--accessibility", "always"] or with the project's accessibility/general/accessibility_support at Always Active, since the engine builds the tree only when asked; reading it takes a second or two, starting PowerShell inside the game so it reaches the game's own desktop`,
|
|
35312
35344
|
requires: []
|
|
35313
35345
|
}
|
|
35314
35346
|
},
|
|
@@ -35438,7 +35470,7 @@ var TOOL_SPECS = [
|
|
|
35438
35470
|
name: "runtime_input",
|
|
35439
35471
|
title: "Send input to the game",
|
|
35440
35472
|
description: "Input to the running game: a whole click on a Control or a 3D node named by path or on a control named by the words on it, an item chosen out of a menu, typing into whatever has the focus, or a raw action, key, mouse button or mouse motion. All of it works headless, where the window is 64 by 64 and the GUI only takes what is inside it. On gdharness's own desktop, where a windowed run goes, Windows refuses to say where the pointer is: every pointer answer there carries pointer_on_hidden_desktop, and the first of the run pointer_note saying why it matters: get_mouse_position() on the root window, and the mouse positions derived from it, read a meaningless position, while what reads the event itself (the control under it, hover, tooltips, input handlers) gets the injected position.",
|
|
35441
|
-
answer: 'click: what was under the pointer, and what became of the control: in_tree, removed or freed. Named by says, found says which match it was, and found.pressedOn says "the words" for words in a RichTextLabel pressed where they are drawn, or "the middle of the label" with a note saying why they could not be placed; on a rich label link_pressed says whether the press reached a link, with link_meta giving the meta the label reports clicked, an empty one included. A control scrolled into view first is scrolled each container out from it a frame after the one inside, and scrolled_into_view says whether a scroll value changed. A button in toggle mode, a CheckBox or CheckButton included, answers pressed with before and after, its button_pressed either side of the click: the same value twice is a click the game undid, and after is null when the click freed it. A refusal for a pointer turned off names where mouse_behavior_recursive was set. On a 3D node landed says the interface did not swallow the press: no control under the pointer stopped it, a control letting the pointer pass included, and every viewport on the way out from the room had the pointer over what shows the room. choose: what was chosen, read before the press, which is heard rather than assumed; what became of the control named (in_tree, removed or freed, since a game can rebuild its screen on the pick); and what the button in front of the menu shows now when it is still there. A menu is opened rather than clicked because its items are drawn rather than built, and the item is looked for as the menu stands once open, since a game can fill a menu as it opens. action, key and
|
|
35473
|
+
answer: 'click: what was under the pointer, and what became of the control: in_tree, removed or freed. Named by says, found says which match it was, and found.pressedOn says "the words" for words in a RichTextLabel pressed where they are drawn, or "the middle of the label" with a note saying why they could not be placed; on a rich label link_pressed says whether the press reached a link, with link_meta giving the meta the label reports clicked, an empty one included. A control scrolled into view first is scrolled each container out from it a frame after the one inside, and scrolled_into_view says whether a scroll value changed. A button in toggle mode, a CheckBox or CheckButton included, answers pressed with before and after, its button_pressed either side of the click: the same value twice is a click the game undid, and after is null when the click freed it. A refusal for a pointer turned off names where mouse_behavior_recursive was set. On a 3D node landed says the interface did not swallow the press: no control under the pointer stopped it, a control letting the pointer pass included, and every viewport on the way out from the room had the pointer over what shows the room. choose: what was chosen, read before the press, which is heard rather than assumed; what became of the control named (in_tree, removed or freed, since a game can rebuild its screen on the pick); and what the button in front of the menu shows now when it is still there. A menu is opened rather than clicked because its items are drawn rather than built, and the item is looked for as the menu stands once open, since a game can fill a menu as it opens. action, key, mouse_click and joypad_button: the event as it was sent, with whole saying whether the press was let go of again, for a key the keycode, physical_keycode and unicode it carried, and for a controller button its number, its name and the device. mouse_motion: the position and the relative movement sent. joypad_motion: the axis by number and name, the value and the device. None of these is aimed at anything, so none says what the event reached: click on a nodePath or says answers what was under the pointer.',
|
|
35442
35474
|
parameters: {
|
|
35443
35475
|
projectPath: RUNNING_PROJECT_PATH,
|
|
35444
35476
|
pid: RUNNING_PID,
|
|
@@ -35459,8 +35491,8 @@ var TOOL_SPECS = [
|
|
|
35459
35491
|
},
|
|
35460
35492
|
pressed: {
|
|
35461
35493
|
type: "boolean",
|
|
35462
|
-
ops: ["action", "key", "mouse_click"],
|
|
35463
|
-
description: "action, key, mouse_click: leave it out and the press is a whole one, down and up a frame apart. true holds it down, false lets go of one being held. A wheel button held down is still a whole step, since a wheel is never held."
|
|
35494
|
+
ops: ["action", "key", "mouse_click", "joypad_button"],
|
|
35495
|
+
description: "action, key, mouse_click, joypad_button: leave it out and the press is a whole one, down and up a frame apart. true holds it down, false lets go of one being held. A wheel button held down is still a whole step, since a wheel is never held."
|
|
35464
35496
|
},
|
|
35465
35497
|
strength: {
|
|
35466
35498
|
type: "number",
|
|
@@ -35505,8 +35537,26 @@ var TOOL_SPECS = [
|
|
|
35505
35537
|
},
|
|
35506
35538
|
button: {
|
|
35507
35539
|
type: ["string", "number"],
|
|
35508
|
-
ops: ["click", "mouse_click"],
|
|
35509
|
-
description: "click, mouse_click: left, right, middle, wheel_up or wheel_down, or a button number. Default left."
|
|
35540
|
+
ops: ["click", "mouse_click", "joypad_button"],
|
|
35541
|
+
description: "click, mouse_click: left, right, middle, wheel_up or wheel_down, or a button number. Default left. joypad_button: the controller button, by name (a, b, x, y, back, guide, start, left_stick, right_stick, left_shoulder, right_shoulder, dpad_up, dpad_down, dpad_left, dpad_right, misc1, paddle1 to paddle4, touchpad) or by its JoyButton number; a, b, x and y are the bottom, right, left and top face buttons, as Godot names them, whatever the controller prints on them."
|
|
35542
|
+
},
|
|
35543
|
+
axis: {
|
|
35544
|
+
type: ["string", "number"],
|
|
35545
|
+
ops: ["joypad_motion"],
|
|
35546
|
+
description: "joypad_motion: the stick or trigger axis, by name (left_x, left_y, right_x, right_y, trigger_left, trigger_right) or by its JoyAxis number."
|
|
35547
|
+
},
|
|
35548
|
+
value: {
|
|
35549
|
+
type: "number",
|
|
35550
|
+
minimum: -1,
|
|
35551
|
+
maximum: 1,
|
|
35552
|
+
ops: ["joypad_motion"],
|
|
35553
|
+
description: "joypad_motion: where the axis is, -1 to 1: down and right are positive on a stick, and a trigger runs 0 to 1. The axis stays there until another motion moves it, as a stick held over does; send 0 to let it go back."
|
|
35554
|
+
},
|
|
35555
|
+
device: {
|
|
35556
|
+
type: "number",
|
|
35557
|
+
minimum: 0,
|
|
35558
|
+
ops: ["joypad_button", "joypad_motion"],
|
|
35559
|
+
description: "joypad_button, joypad_motion: which controller, counting from 0. Default 0."
|
|
35510
35560
|
},
|
|
35511
35561
|
doubleClick: {
|
|
35512
35562
|
type: "boolean",
|
|
@@ -35556,6 +35606,16 @@ var TOOL_SPECS = [
|
|
|
35556
35606
|
effect: "additive",
|
|
35557
35607
|
summary: "move the mouse to a position, carrying the distance from where the last injected event put it unless relativeX and relativeY say otherwise, and the buttons held, so a control that drags moves under a run of these between a held mouse_click and its release",
|
|
35558
35608
|
requires: ["x", "y"]
|
|
35609
|
+
},
|
|
35610
|
+
joypad_button: {
|
|
35611
|
+
effect: "additive",
|
|
35612
|
+
summary: "press a controller button, or hold it, as an InputEventJoypadButton, so a game reading the pad in _input or _unhandled_input gets what a controller sends; an action bound to the button fires with it, as it would for a real one. Pressed and released a frame apart unless pressed says otherwise",
|
|
35613
|
+
requires: ["button"]
|
|
35614
|
+
},
|
|
35615
|
+
joypad_motion: {
|
|
35616
|
+
effect: "additive",
|
|
35617
|
+
summary: "move a stick or trigger axis to a value, as an InputEventJoypadMotion, which is what a game reading the sticks gets; the axis stays there until another motion moves it",
|
|
35618
|
+
requires: ["axis", "value"]
|
|
35559
35619
|
}
|
|
35560
35620
|
}
|
|
35561
35621
|
},
|
|
@@ -38014,6 +38074,12 @@ class GodotServer {
|
|
|
38014
38074
|
path: readNonEmptyString(args, "nodePath") ?? "",
|
|
38015
38075
|
property: readNonEmptyString(args, "property") ?? ""
|
|
38016
38076
|
}, { tool: "runtime_inspect", op, patience });
|
|
38077
|
+
case "accessibility":
|
|
38078
|
+
return await this.handleRuntimeCommand("get_accessibility", whichGame(args), {
|
|
38079
|
+
tool: "runtime_inspect",
|
|
38080
|
+
op,
|
|
38081
|
+
patience: readPositiveNumber(args, "timeoutMs") ?? Math.max(30000, this.runtimeTimeoutMs())
|
|
38082
|
+
});
|
|
38017
38083
|
default:
|
|
38018
38084
|
return await this.handleRuntimeCommand("get_metrics", { ...whichGame(args), metrics: readArray(args, "metrics") ?? [] }, { tool: "runtime_inspect", op, patience });
|
|
38019
38085
|
}
|
package/build/keeper.js
CHANGED
|
@@ -386,7 +386,10 @@ var ENGINE_FLAGS = Object.freeze({
|
|
|
386
386
|
"--fixed-fps": "number",
|
|
387
387
|
"--max-fps": "number",
|
|
388
388
|
"--resolution": "size",
|
|
389
|
-
"--write-movie": "file"
|
|
389
|
+
"--write-movie": "file",
|
|
390
|
+
"--rendering-driver": "driver",
|
|
391
|
+
"--rendering-method": "method",
|
|
392
|
+
"--accessibility": "accessibility"
|
|
390
393
|
});
|
|
391
394
|
var SET_BY_ARGUMENT = Object.freeze({
|
|
392
395
|
"--headless": "headless",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.26",
|
|
4
4
|
"mcpName": "io.github.Aureliolo/gdharness",
|
|
5
5
|
"description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
|
|
6
6
|
"type": "module",
|