gdharness 1.3.41 → 1.3.43

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.
Files changed (107) hide show
  1. package/build/cli.js +131 -47
  2. package/build/godot/addons/auto_reload/auto_reload.gd +18 -19
  3. package/build/godot/addons/gdharness_editor/animation_reads.gd +84 -35
  4. package/build/godot/addons/gdharness_editor/bridge_client.gd +53 -58
  5. package/build/godot/addons/gdharness_editor/declared_values.gd +68 -32
  6. package/build/godot/addons/gdharness_editor/file_reads.gd +114 -39
  7. package/build/godot/addons/gdharness_editor/file_walk.gd +12 -5
  8. package/build/godot/addons/gdharness_editor/headless_check.gd +94 -41
  9. package/build/godot/addons/gdharness_editor/plugin.gd +2 -3
  10. package/build/godot/addons/gdharness_editor/property_paths.gd +22 -12
  11. package/build/godot/addons/gdharness_editor/property_values.gd +143 -78
  12. package/build/godot/addons/gdharness_editor/reading.gd +37 -12
  13. package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
  14. package/build/godot/addons/gdharness_editor/scene_file.gd +136 -79
  15. package/build/godot/addons/gdharness_editor/scene_uids.gd +12 -6
  16. package/build/godot/addons/gdharness_editor/serialisation.gd +75 -51
  17. package/build/godot/addons/gdharness_editor/setting_reads.gd +7 -6
  18. package/build/godot/addons/gdharness_editor/tool_executor.gd +3 -6
  19. package/build/godot/addons/gdharness_editor/tools/animation_states.gd +41 -28
  20. package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +84 -50
  21. package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +70 -40
  22. package/build/godot/addons/gdharness_editor/tools/class_tools.gd +34 -30
  23. package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +24 -22
  24. package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd +49 -29
  25. package/build/godot/addons/gdharness_editor/tools/play_tools.gd +26 -21
  26. package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +40 -40
  27. package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +181 -107
  28. package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +16 -9
  29. package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +75 -43
  30. package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +35 -20
  31. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +28 -13
  32. package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd +66 -0
  33. package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd.uid +1 -0
  34. package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +171 -62
  35. package/build/godot/addons/gdharness_editor/tools/script_paths.gd +20 -8
  36. package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +11 -8
  37. package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +47 -34
  38. package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +77 -50
  39. package/build/godot/addons/gdharness_editor/value_shapes.gd +5 -6
  40. package/build/godot/addons/gdharness_runtime/call_errors.gd +1 -2
  41. package/build/godot/addons/gdharness_runtime/declared_values.gd +68 -32
  42. package/build/godot/addons/gdharness_runtime/error_report.gd +1 -2
  43. package/build/godot/addons/gdharness_runtime/reading.gd +37 -12
  44. package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +84 -63
  45. package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +153 -148
  46. package/build/godot/addons/gdharness_runtime/runtime_capture.gd +64 -42
  47. package/build/godot/addons/gdharness_runtime/runtime_changes.gd +184 -122
  48. package/build/godot/addons/gdharness_runtime/runtime_frames.gd +2 -2
  49. package/build/godot/addons/gdharness_runtime/runtime_hover.gd +24 -20
  50. package/build/godot/addons/gdharness_runtime/runtime_input.gd +134 -92
  51. package/build/godot/addons/gdharness_runtime/runtime_items.gd +29 -13
  52. package/build/godot/addons/gdharness_runtime/runtime_menus.gd +0 -1
  53. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +38 -20
  54. package/build/godot/addons/gdharness_runtime/runtime_pad.gd +17 -13
  55. package/build/godot/addons/gdharness_runtime/runtime_paths.gd +84 -46
  56. package/build/godot/addons/gdharness_runtime/runtime_queries.gd +117 -79
  57. package/build/godot/addons/gdharness_runtime/runtime_says.gd +14 -17
  58. package/build/godot/addons/gdharness_runtime/runtime_screen.gd +23 -16
  59. package/build/godot/addons/gdharness_runtime/runtime_targets.gd +117 -66
  60. package/build/godot/addons/gdharness_runtime/runtime_touch.gd +211 -0
  61. package/build/godot/addons/gdharness_runtime/runtime_touch.gd.uid +1 -0
  62. package/build/godot/addons/gdharness_runtime/runtime_typing.gd +44 -27
  63. package/build/godot/addons/gdharness_runtime/runtime_values.gd +108 -73
  64. package/build/godot/addons/gdharness_runtime/runtime_waits.gd +111 -84
  65. package/build/godot/addons/gdharness_runtime/runtime_words.gd +10 -7
  66. package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -51
  67. package/build/godot/addons/gdharness_runtime/value_shapes.gd +5 -6
  68. package/build/godot/addons/gdharness_tests/bench.gd +4 -5
  69. package/build/godot/addons/gdharness_tests/event.gd +10 -5
  70. package/build/godot/addons/gdharness_tests/share.gd +38 -18
  71. package/build/godot/addons/gdharness_tests/suites.gd +3 -3
  72. package/build/godot/addons/gdharness_tests/wait.gd +3 -2
  73. package/build/godot/loader/loader.gd +9 -9
  74. package/build/godot/operations/animation_reads.gd +84 -35
  75. package/build/godot/operations/audio_buses.gd +48 -19
  76. package/build/godot/operations/class_cache.gd +16 -11
  77. package/build/godot/operations/classdb_queries.gd +89 -44
  78. package/build/godot/operations/declared_values.gd +68 -32
  79. package/build/godot/operations/dependencies.gd +139 -93
  80. package/build/godot/operations/editor_tools.gd +9 -10
  81. package/build/godot/operations/export_presets.gd +100 -54
  82. package/build/godot/operations/file_reads.gd +114 -39
  83. package/build/godot/operations/file_walk.gd +12 -5
  84. package/build/godot/operations/gdscript_analysis.gd +105 -66
  85. package/build/godot/operations/gdscript_authoring.gd +138 -39
  86. package/build/godot/operations/godot_operations.gd +17 -11
  87. package/build/godot/operations/import_pipeline.gd +110 -59
  88. package/build/godot/operations/input_actions.gd +63 -39
  89. package/build/godot/operations/patterns.gd +3 -1
  90. package/build/godot/operations/plugins.gd +36 -16
  91. package/build/godot/operations/project_config.gd +144 -27
  92. package/build/godot/operations/project_diagnostics.gd +24 -11
  93. package/build/godot/operations/project_file.gd +16 -16
  94. package/build/godot/operations/project_validation.gd +71 -44
  95. package/build/godot/operations/property_paths.gd +22 -12
  96. package/build/godot/operations/property_values.gd +143 -78
  97. package/build/godot/operations/reading.gd +37 -12
  98. package/build/godot/operations/rename_checks.gd +2 -2
  99. package/build/godot/operations/resource_files.gd +11 -9
  100. package/build/godot/operations/same_values.gd +4 -4
  101. package/build/godot/operations/scene_connections.gd +27 -13
  102. package/build/godot/operations/script_check.gd +52 -49
  103. package/build/godot/operations/serialisation.gd +75 -51
  104. package/build/godot/operations/setting_reads.gd +7 -6
  105. package/build/godot/operations/value_shapes.gd +5 -6
  106. package/build/godot/tests/listed.gd +321 -268
  107. package/package.json +1 -1
@@ -1,17 +1,15 @@
1
1
  extends RefCounted
2
-
3
- ## What the server changes in the running game: a property written, a method called. Both take values
4
- ## from the wire, so both fit them to what the game declares and refuse what cannot fit, and both read
5
- ## back what the engine did rather than trusting that it did it.
2
+ ## What the server changes in the running game: a property written, a method called. Both take
3
+ ## values from the wire, so both fit them to what the game declares and refuse what cannot fit, and
4
+ ## both read back what the engine did rather than trusting that it did it.
6
5
 
7
6
  const GdhCallErrors = preload("call_errors.gd")
8
7
  const GdhDeclared = preload("declared_values.gd")
9
8
  const GdhPaths = preload("runtime_paths.gd")
10
9
  const GdhRead = preload("reading.gd")
11
10
  const GdhValues = preload("runtime_values.gd")
12
-
13
- ## The most errors a call's answer carries, which is enough to see what the method ran into and short
14
- ## of a method reporting one per element of a list of thousands.
11
+ ## The most errors a call's answer carries, which is enough to see what the method ran into and
12
+ ## short of a method reporting one per element of a list of thousands.
15
13
  const ERRORS_KEPT: int = 20
16
14
 
17
15
  var _host: Node
@@ -31,7 +29,7 @@ func set_property(params: Dictionary) -> Dictionary:
31
29
  var value: Variant = params.get("value")
32
30
 
33
31
  if node_path.is_empty() or property.is_empty():
34
- return {"type": "error", "message": "Node path and property required"}
32
+ return { "type": "error", "message": "Node path and property required" }
35
33
 
36
34
  var standing: Dictionary = GdhValues.target_at(_host.get_tree().root, node_path)
37
35
  if standing.has("message"):
@@ -39,9 +37,9 @@ func set_property(params: Dictionary) -> Dictionary:
39
37
  var node: Node = standing["node"]
40
38
  var target: Object = standing["object"]
41
39
 
42
- # Through a path as well, for the reason [method GdhPaths.walk_to] gives, and read back off the same
43
- # holder afterwards: a set that does not take says so by answering with the old value, which is
44
- # how a typed container refusing a write is told from one accepting it.
40
+ # Through a path as well, for the reason [method GdhPaths.walk_to] gives, and read back off the
41
+ # same holder afterwards: a set that does not take says so by answering with the old value,
42
+ # which is how a typed container refusing a write is told from one accepting it.
45
43
  var reached: Dictionary = GdhPaths.walk_to(target, node_path, property)
46
44
  if reached.has("message"):
47
45
  return reached
@@ -57,10 +55,13 @@ func set_property(params: Dictionary) -> Dictionary:
57
55
  (
58
56
  "%s:%s is a call, and a call is not a place to write: name a property"
59
57
  % [reached["called"], named]
60
- )
58
+ ),
61
59
  }
62
60
  if not GdhPaths.can_read(holder, named):
63
- return {"type": "error", "message": GdhPaths.nothing_there(holder, named, str(reached["called"]))}
61
+ return {
62
+ "type": "error",
63
+ "message": GdhPaths.nothing_there(holder, named, str(reached["called"])),
64
+ }
64
65
  var old_value: Variant = GdhPaths.read_under(holder, named)
65
66
  var slot: Dictionary = GdhValues.slot_declared(holder, named)
66
67
  var declared: int = slot["type"]
@@ -77,7 +78,7 @@ func set_property(params: Dictionary) -> Dictionary:
77
78
  if copied:
78
79
  var unwritable: String = GdhPaths.unwritable_copy(chain)
79
80
  if not unwritable.is_empty():
80
- return {"type": "error", "message": unwritable}
81
+ return { "type": "error", "message": unwritable }
81
82
  # The write alone, setter included, which is where a property's cost is. Listened to as a call
82
83
  # is, since a setter refusing a value says why only in what it reports.
83
84
  var caught: GdhCallErrors = GdhCallErrors.new()
@@ -102,10 +103,11 @@ func set_property(params: Dictionary) -> Dictionary:
102
103
  # And only one that asked for a change: the value the property already held, written again, left
103
104
  # it as it was because nothing was asked of it.
104
105
  #
105
- # Said as what was seen, because two causes look the same from here: the engine refusing the write,
106
- # and a setter that ran and left the value where it was, clamping it, say. The one this can name
107
- # is an object slot checked only by the engine class a script extends (see
108
- # [method GdhValues.slot_declared]), where an object of that class with another script is refused.
106
+ # Said as what was seen, because two causes look the same from here: the engine refusing the
107
+ # write, and a setter that ran and left the value where it was, clamping it, say. The one this
108
+ # can name is an object slot checked only by the engine class a script extends (see
109
+ # [method GdhValues.slot_declared]), where an object of that class with another script is
110
+ # refused.
109
111
  #
110
112
  # Judged by what reads back alone, so a value of another kind than the one held, which cannot be
111
113
  # compared with it, is still caught when the engine drops it.
@@ -113,16 +115,16 @@ func set_property(params: Dictionary) -> Dictionary:
113
115
  var unmoved: bool = GdhValues.comparable(now, old_value) and now == old_value
114
116
  if unmoved and not already:
115
117
  var why: String = (
116
- "the write left it as it was, which is what the engine refusing it and a setter keeping the"
117
- + " value both look like"
118
+ "the write left it as it was, which is what the engine refusing it and a setter "
119
+ + "keeping the value both look like"
118
120
  )
119
121
  if declared == TYPE_OBJECT and given is Object and declared_script == null:
120
122
  var refused_object: Object = given
121
123
  why += (
122
124
  (
123
- ". %s is declared as %s, which is also how the engine names a script class with no"
124
- + " class_name; if it is one, the object given has the right class and another script:"
125
- + " it is %s"
125
+ ". %s is declared as %s, which is also how the engine names a script class "
126
+ + "with no class_name; if it is one, the object given has the right class and "
127
+ + "another script: it is %s"
126
128
  )
127
129
  % [named, str(slot["class"]), GdhValues.class_of(refused_object)]
128
130
  )
@@ -139,7 +141,7 @@ func set_property(params: Dictionary) -> Dictionary:
139
141
  if not caught.raised.is_empty():
140
142
  var reported: PackedStringArray = PackedStringArray(caught.raised.slice(0, ERRORS_KEPT))
141
143
  refused += " While it was written the game reported: %s" % "; ".join(reported)
142
- return {"type": "error", "message": refused}
144
+ return { "type": "error", "message": refused }
143
145
 
144
146
  var answer: Dictionary = {
145
147
  "type": "property_set",
@@ -147,14 +149,15 @@ func set_property(params: Dictionary) -> Dictionary:
147
149
  "property": property,
148
150
  "old_value": _values.serialize(old_value),
149
151
  "new_value": _values.serialize(now),
150
- "elapsed_usec": elapsed
152
+ "elapsed_usec": elapsed,
151
153
  }
152
154
  if already and unmoved:
153
155
  answer["unchanged"] = true
154
156
  _keep_reported(answer, "errors", caught.raised)
155
157
  _keep_reported(answer, "warnings", caught.warned)
156
158
  # The engine stores a number past an export range, or one no enum value has, as given; only the
157
- # inspector holds a property to them, so the game now holds a value its own script never expected.
159
+ # inspector holds a property to them, so the game now holds a value its own script never
160
+ # expected.
158
161
  if holder is Object:
159
162
  var owner: Object = holder
160
163
  var shown: String = JSON.stringify(_values.serialize(now), "", false)
@@ -166,9 +169,9 @@ func set_property(params: Dictionary) -> Dictionary:
166
169
 
167
170
 
168
171
  ## What [param sent] becomes as argument [param index] of the method [param named] on the holder
169
- ## [param reached] ends at, as [method GdhPaths.walk_to] answered it, as `{"value": ...}`, or the refusal
170
- ## saying why it cannot become one: a number the parameter would have to cut, a value that cannot be
171
- ## converted, or a list or map that cannot be built as the typed one the parameter takes.
172
+ ## [param reached] ends at, as [method GdhPaths.walk_to] answered it, as `{"value": ...}`, or the
173
+ ## refusal saying why it cannot become one: a number the parameter would have to cut, a value that
174
+ ## cannot be converted, or a list or map that cannot be built as the typed one the parameter takes.
172
175
  func _argument_for(
173
176
  sent: Variant, index: int, reached: Dictionary, named: String, node: Node, node_path: String
174
177
  ) -> Dictionary:
@@ -185,14 +188,17 @@ func _argument_for(
185
188
  "message":
186
189
  GdhDeclared.enum_argument_refusal(
187
190
  "%s.%s" % [called, named], index, str(choices["enum"]), str(sent), values
188
- )
191
+ ),
189
192
  }
190
- return {"value": chosen}
193
+ return { "value": chosen }
191
194
  # A packed list's elements are fitted one by one, and one that cannot become what the list holds
192
- # is named: converted whole, a word or a fraction among them became 0 or was cut, and the call ran.
195
+ # is named: converted whole, a word or a fraction among them became 0 or was cut, and the call
196
+ # ran.
193
197
  var packed: Variant = GdhValues.packed_template(wants)
194
198
  if packed != null and sent is Array:
195
- var elements: Dictionary = _values.typed_like(sent, packed, _element_object.bind(node, node_path))
199
+ var elements: Dictionary = _values.typed_like(
200
+ sent, packed, _element_object.bind(node, node_path)
201
+ )
196
202
  if elements.has("message"):
197
203
  return {
198
204
  "type": "error",
@@ -200,29 +206,32 @@ func _argument_for(
200
206
  (
201
207
  "%s.%s takes %s as argument %d: %s"
202
208
  % [called, named, type_string(wants), index + 1, elements["message"]]
203
- )
209
+ ),
204
210
  }
205
211
  if GdhValues.cuts(sent, wants):
206
212
  return {
207
213
  "type": "error",
208
214
  "message":
209
215
  (
210
- "%s.%s takes %s as argument %d and was given %s, which %s cannot hold without changing it"
216
+ (
217
+ "%s.%s takes %s as argument %d and was given %s, which %s cannot hold without "
218
+ + "changing it"
219
+ )
211
220
  % [
212
221
  called,
213
222
  named,
214
223
  type_string(wants),
215
224
  index + 1,
216
225
  JSON.stringify(sent),
217
- GdhValues.cut_by(wants)
226
+ GdhValues.cut_by(wants),
218
227
  ]
219
- )
228
+ ),
220
229
  }
221
230
  var rounded: String = GdhValues.inexact(sent, wants)
222
231
  if not rounded.is_empty():
223
232
  return {
224
233
  "type": "error",
225
- "message": "%s.%s takes int as argument %d: %s." % [called, named, index + 1, rounded]
234
+ "message": "%s.%s takes int as argument %d: %s." % [called, named, index + 1, rounded],
226
235
  }
227
236
  var given: Variant = _values.fitted(sent, wants)
228
237
  if not GdhValues.acceptable(given, wants):
@@ -237,16 +246,18 @@ func _argument_for(
237
246
  type_string(wants),
238
247
  index + 1,
239
248
  type_string(typeof(given)),
240
- GdhValues.remedy(sent, wants)
249
+ GdhValues.remedy(sent, wants),
241
250
  ]
242
- )
251
+ ),
243
252
  }
244
253
  # A typed list or map is built as one, since a plain one handed to such a parameter raises
245
254
  # inside the game, which is what every check here exists to stop.
246
255
  var container: Variant = _values.parameter_container(holder, named, index)
247
256
  if container == null:
248
- return {"value": given}
249
- var typed: Dictionary = _values.typed_like(given, container, _element_object.bind(node, node_path))
257
+ return { "value": given }
258
+ var typed: Dictionary = _values.typed_like(
259
+ given, container, _element_object.bind(node, node_path)
260
+ )
250
261
  if typed.has("message"):
251
262
  return {
252
263
  "type": "error",
@@ -254,14 +265,14 @@ func _argument_for(
254
265
  (
255
266
  "%s.%s takes a typed %s as argument %d: %s"
256
267
  % [called, named, _sort_of(container), index + 1, typed["message"]]
257
- )
268
+ ),
258
269
  }
259
- return {"value": typed["value"]}
270
+ return { "value": typed["value"] }
260
271
 
261
272
 
262
273
  ## What [param value] becomes written into the slot [param reached] ends on, as
263
- ## [method GdhPaths.walk_to] answered it, as `{"value": ...}`, or the refusal saying why it cannot become
264
- ## one.
274
+ ## [method GdhPaths.walk_to] answered it, as `{"value": ...}`, or the refusal saying why it cannot
275
+ ## become one.
265
276
  ##
266
277
  ## The same rule the call path holds: a value that cannot become what the property holds is
267
278
  ## refused rather than written. Writing it means the engine picks something, and what it picks
@@ -276,7 +287,12 @@ func _argument_for(
276
287
  ## the number, not its text. The text null empties it when it holds an object or nothing, as a wait
277
288
  ## reads it on the same slot.
278
289
  func _value_for(
279
- value: Variant, slot: Dictionary, old_value: Variant, reached: Dictionary, node: Node, node_path: String
290
+ value: Variant,
291
+ slot: Dictionary,
292
+ old_value: Variant,
293
+ reached: Dictionary,
294
+ node: Node,
295
+ node_path: String
280
296
  ) -> Dictionary:
281
297
  var named: String = reached["name"]
282
298
  var called: String = reached["called"]
@@ -284,27 +300,33 @@ func _value_for(
284
300
  var declared_script: Script = slot["script"]
285
301
  var wanted: int = declared if declared != TYPE_NIL else typeof(old_value)
286
302
  var declaration: Dictionary = slot["declared"]
287
- var enum_hint: bool = GdhRead.as_int(declaration.get("hint", PROPERTY_HINT_NONE)) == PROPERTY_HINT_ENUM
303
+ var enum_hint: bool = (
304
+ GdhRead.as_int(declaration.get("hint", PROPERTY_HINT_NONE)) == PROPERTY_HINT_ENUM
305
+ )
288
306
  if declared == TYPE_INT and enum_hint and value is String and reached["holder"] is Object:
289
307
  var owner: Object = reached["holder"]
290
308
  var by_name: Array = GdhDeclared.enum_by_name(owner, declaration, str(value), called)
291
309
  if by_name[0]:
292
- return {"value": by_name[1]}
310
+ return { "value": by_name[1] }
293
311
  if not str(by_name[1]).is_empty():
294
- return {"type": "error", "message": by_name[1]}
312
+ return { "type": "error", "message": by_name[1] }
295
313
  var packed: Variant = GdhValues.packed_template(wanted)
296
314
  if packed != null and value is Array:
297
- var elements: Dictionary = _values.typed_like(value, packed, _element_object.bind(node, node_path))
315
+ var elements: Dictionary = _values.typed_like(
316
+ value, packed, _element_object.bind(node, node_path)
317
+ )
298
318
  if elements.has("message"):
299
319
  return {
300
320
  "type": "error",
301
- "message": "%s.%s holds %s: %s" % [called, named, type_string(wanted), elements["message"]]
321
+ "message":
322
+ "%s.%s holds %s: %s" % [called, named, type_string(wanted), elements["message"]],
302
323
  }
303
324
  var holds_objects: bool = (
304
- declared == TYPE_OBJECT or (declared == TYPE_NIL and (old_value == null or old_value is Object))
325
+ declared == TYPE_OBJECT
326
+ or (declared == TYPE_NIL and (old_value == null or old_value is Object))
305
327
  )
306
328
  if holds_objects and names_no_object(value):
307
- return {"value": null}
329
+ return { "value": null }
308
330
  if wanted == TYPE_OBJECT and (value is String or value is Dictionary):
309
331
  var named_object: Dictionary = _object_named(
310
332
  node, node_path, value, str(slot["class"]), declared_script
@@ -312,12 +334,12 @@ func _value_for(
312
334
  if named_object.has("message"):
313
335
  return {
314
336
  "type": "error",
315
- "message": "%s.%s holds an object: %s" % [called, named, named_object["message"]]
337
+ "message": "%s.%s holds an object: %s" % [called, named, named_object["message"]],
316
338
  }
317
- return {"value": named_object["object"]}
339
+ return { "value": named_object["object"] }
318
340
  var rounded: String = GdhValues.inexact(value, wanted)
319
341
  if not rounded.is_empty():
320
- return {"type": "error", "message": "%s.%s holds int: %s." % [called, named, rounded]}
342
+ return { "type": "error", "message": "%s.%s holds int: %s." % [called, named, rounded] }
321
343
  var as_sent: Variant = _values.fitted(value, TYPE_NIL)
322
344
  var cut: bool = GdhValues.cuts(value, wanted)
323
345
  var given: Variant = as_sent
@@ -327,8 +349,14 @@ func _value_for(
327
349
  "message":
328
350
  (
329
351
  "%s.%s holds %s and the value given is %s, which %s cannot hold without changing it"
330
- % [called, named, type_string(wanted), JSON.stringify(value), GdhValues.cut_by(wanted)]
331
- )
352
+ % [
353
+ called,
354
+ named,
355
+ type_string(wanted),
356
+ JSON.stringify(value),
357
+ GdhValues.cut_by(wanted),
358
+ ]
359
+ ),
332
360
  }
333
361
  if declared != TYPE_NIL or (not cut and GdhValues.acceptable(as_sent, wanted)):
334
362
  given = _values.fitted(value, wanted)
@@ -343,17 +371,20 @@ func _value_for(
343
371
  named,
344
372
  type_string(wanted),
345
373
  type_string(typeof(given)),
346
- GdhValues.remedy(value, wanted)
374
+ GdhValues.remedy(value, wanted),
347
375
  ]
348
- )
376
+ ),
349
377
  }
350
- var typed: Dictionary = _values.typed_like(given, old_value, _element_object.bind(node, node_path))
378
+ var typed: Dictionary = _values.typed_like(
379
+ given, old_value, _element_object.bind(node, node_path)
380
+ )
351
381
  if typed.has("message"):
352
382
  return {
353
383
  "type": "error",
354
- "message": "%s.%s is a typed %s: %s" % [called, named, _sort_of(old_value), typed["message"]]
384
+ "message":
385
+ "%s.%s is a typed %s: %s" % [called, named, _sort_of(old_value), typed["message"]],
355
386
  }
356
- return {"value": typed["value"]}
387
+ return { "value": typed["value"] }
357
388
 
358
389
 
359
390
  ## Whether [param given] is the value [param held] already is, at the precision the property keeps.
@@ -376,9 +407,9 @@ static func held_already(given: Variant, held: Variant) -> bool:
376
407
  return PackedFloat32Array([given])[0] == PackedFloat32Array([held])[0]
377
408
 
378
409
 
379
- ## What to do instead of the call [param method] makes on [param sort], the list or map [param
380
- ## reached] ends on, which a path does not make. A method of the list itself is the likelier aim
381
- ## than one of what it holds when the list has it: told to call append() on an element, a caller
410
+ ## What to do instead of the call [param method] makes on [param sort], the list or map
411
+ ## [param reached] ends on, which a path does not make. A method of the list itself is the likelier
412
+ ## aim than one of what it holds when the list has it: told to call append() on an element, a caller
382
413
  ## adding to a list has nowhere to go.
383
414
  static func _instead_of_a_call(reached: Dictionary, method: String, sort: String) -> String:
384
415
  var own: String = GdhPaths.method_of(str(reached["name"]))
@@ -396,23 +427,25 @@ static func _instead_of_a_call(reached: Dictionary, method: String, sort: String
396
427
  if through_a_call:
397
428
  return (
398
429
  (
399
- "%s() changes %s: to change it, call a method of the game that changes it, since %s"
400
- + " is returned by a call, and runtime_invoke set does not write into what a call returns"
430
+ "%s() changes %s: to change it, call a method of the game that changes it, "
431
+ + "since %s is returned by a call, and runtime_invoke set does not write "
432
+ + "into what a call returns"
401
433
  )
402
434
  % [own, the, reached["called"]]
403
435
  )
404
436
  return (
405
437
  (
406
- "%s() changes %s: to change it, give %s its new value whole with runtime_invoke set,"
407
- + " property %s, or call a method of the game that changes it"
438
+ "%s() changes %s: to change it, give %s its new value whole with "
439
+ + "runtime_invoke set, property %s, or call a method of the game that changes "
440
+ + "it"
408
441
  )
409
442
  % [own, the, reached["called"], holding]
410
443
  )
411
444
  "reads":
412
445
  return (
413
446
  (
414
- "To look in %s with %s(), read %s whole with runtime_inspect property, property %s, and"
415
- + " look in what comes back"
447
+ "To look in %s with %s(), read %s whole with runtime_inspect property, "
448
+ + "property %s, and look in what comes back"
416
449
  )
417
450
  % [the, own, reached["called"], holding]
418
451
  )
@@ -428,7 +461,7 @@ func call_method(params: Dictionary) -> Dictionary:
428
461
  var args: Array = params.get("args", [])
429
462
 
430
463
  if node_path.is_empty() or method.is_empty():
431
- return {"type": "error", "message": "Node path and method required"}
464
+ return { "type": "error", "message": "Node path and method required" }
432
465
 
433
466
  var root: Node = _host.get_tree().root
434
467
  var standing: Dictionary = GdhValues.class_at(root, node_path)
@@ -441,8 +474,8 @@ func call_method(params: Dictionary) -> Dictionary:
441
474
  var close: PackedStringArray = GdhRead.nearest(node_path, PackedStringArray(classes))
442
475
  standing["message"] = (
443
476
  (
444
- "%s. No global class is called %s either%s; a static function is called with its"
445
- + " class's name or its script's res:// path as the path."
477
+ "%s. No global class is called %s either%s; a static function is called with "
478
+ + "its class's name or its script's res:// path as the path."
446
479
  )
447
480
  % [
448
481
  str(standing["message"]).trim_suffix("."),
@@ -462,8 +495,8 @@ func call_method(params: Dictionary) -> Dictionary:
462
495
  var node: Node = standing["node"]
463
496
  var target: Object = standing["object"]
464
497
 
465
- # Through a path as well, for the reason [method GdhPaths.walk_to] gives. What a game does hangs off its
466
- # nodes as much as its state does, so reading `_game:run:day` while being unable to call
498
+ # Through a path as well, for the reason [method GdhPaths.walk_to] gives. What a game does hangs
499
+ # off its nodes as much as its state does, so reading `_game:run:day` while being unable to call
467
500
  # `_game:run:advance` answers half of what a node holds and refuses the other half.
468
501
  var reached: Dictionary = GdhPaths.walk_to(target, node_path, method)
469
502
  if reached.has("message"):
@@ -471,7 +504,8 @@ func call_method(params: Dictionary) -> Dictionary:
471
504
 
472
505
  # A list or a map answers the calls a path makes on one, and nothing else: said in those terms
473
506
  # rather than as "has no method", which reads as a misspelling of a method that was never going
474
- # to be there, and with the element spelled out, since a method on what it holds is the usual aim.
507
+ # to be there, and with the element spelled out, since a method on what it holds is the usual
508
+ # aim.
475
509
  if not reached["holder"] is Object:
476
510
  var sort: String = "a list"
477
511
  if reached["holder"] is Dictionary:
@@ -481,8 +515,8 @@ func call_method(params: Dictionary) -> Dictionary:
481
515
  var spelled: String = str(reached["name"])
482
516
  if GdhPaths.method_of(spelled).is_empty():
483
517
  spelled += "()"
484
- # A vector or a transform has no element to call a method on, so a call it does not answer is
485
- # refused without the advice about elements below.
518
+ # A vector or a transform has no element to call a method on, so a call it does not answer
519
+ # is refused without the advice about elements below.
486
520
  var answers: bool = GdhPaths.can_read(reached["holder"], spelled)
487
521
  var called_on: Variant = reached["holder"]
488
522
  if (
@@ -496,7 +530,7 @@ func call_method(params: Dictionary) -> Dictionary:
496
530
  "%s:%s takes no arguments" % [reached["called"], spelled]
497
531
  if answers
498
532
  else GdhPaths.nothing_there(reached["holder"], spelled, str(reached["called"]))
499
- )
533
+ ),
500
534
  }
501
535
  if args.is_empty() and answers:
502
536
  var read_from: int = Time.get_ticks_usec()
@@ -518,7 +552,9 @@ func call_method(params: Dictionary) -> Dictionary:
518
552
  if GdhPaths.can_read(reached["holder"], spelled)
519
553
  else GdhPaths.nothing_there(reached["holder"], spelled, str(reached["called"]))
520
554
  )
521
- return {"type": "error", "message": "%s. %s" % [why, _instead_of_a_call(reached, method, sort)]}
555
+ return {
556
+ "type": "error", "message": "%s. %s" % [why, _instead_of_a_call(reached, method, sort)],
557
+ }
522
558
  var holder: Object = reached["holder"]
523
559
  var named: String = reached["name"]
524
560
  # The method a call ends on is the one being called whether or not it carries the brackets a
@@ -532,7 +568,7 @@ func call_method(params: Dictionary) -> Dictionary:
532
568
  if not_called.is_empty():
533
569
  not_called = _not_a_method_to_call(holder, named, str(reached["called"]))
534
570
  if not not_called.is_empty():
535
- return {"type": "error", "message": not_called}
571
+ return { "type": "error", "message": not_called }
536
572
  if not GdhPaths.method_of(named).is_empty():
537
573
  named = GdhPaths.method_of(named)
538
574
 
@@ -542,10 +578,10 @@ func call_method(params: Dictionary) -> Dictionary:
542
578
  # nowhere near the argument. A wrong argument costs a refusal, never the session's game.
543
579
  var count: String = _argument_count_refused(holder, named, args.size())
544
580
  if not count.is_empty():
545
- return {"type": "error", "message": "%s.%s %s" % [reached["called"], named, count]}
581
+ return { "type": "error", "message": "%s.%s %s" % [reached["called"], named, count] }
546
582
  var deserialized_args: Array = []
547
- # The object arguments checked only against the engine class, by position from 1, for the refusal
548
- # the engine may still make: see [method GdhValues.slot_declared].
583
+ # The object arguments checked only against the engine class, by position from 1, for the
584
+ # refusal the engine may still make: see [method GdhValues.slot_declared].
549
585
  var by_engine_class: Dictionary = {}
550
586
  # The enum arguments given a number none of their values has, said beside the answer: the engine
551
587
  # passes any number on, and a write of the same number to a property already said so.
@@ -559,14 +595,19 @@ func call_method(params: Dictionary) -> Dictionary:
559
595
  return {
560
596
  "type": "error",
561
597
  "message":
562
- "%s.%s argument %d: %s" % [reached["called"], named, index + 1, named_object["message"]]
598
+ (
599
+ "%s.%s argument %d: %s"
600
+ % [reached["called"], named, index + 1, named_object["message"]]
601
+ ),
563
602
  }
564
603
  var resolved: Object = named_object["object"]
565
604
  if resolved != null and ClassDB.class_exists(declared):
566
605
  by_engine_class[index + 1] = [declared, GdhValues.class_of(resolved)]
567
606
  deserialized_args.append(named_object["object"])
568
607
  continue
569
- var argument: Dictionary = _argument_for(args[index], index, reached, named, node, node_path)
608
+ var argument: Dictionary = _argument_for(
609
+ args[index], index, reached, named, node, node_path
610
+ )
570
611
  if argument.has("message"):
571
612
  return argument
572
613
  deserialized_args.append(argument["value"])
@@ -601,27 +642,27 @@ func call_method(params: Dictionary) -> Dictionary:
601
642
  "%s.%s did not run: the engine refused the call: %s"
602
643
  % [reached["called"], named, caught.refused.trim_suffix(".")]
603
644
  )
604
- var position: RegExMatch = RegEx.create_from_string(r"Cannot convert argument (\d+)").search(
605
- caught.refused
645
+ var position: RegExMatch = (
646
+ RegEx.create_from_string(r"Cannot convert argument (\d+)").search(caught.refused)
606
647
  )
607
648
  if position != null and by_engine_class.has(int(position.get_string(1))):
608
649
  var checked: Array = by_engine_class[int(position.get_string(1))]
609
650
  message += (
610
651
  (
611
- ". The parameter is declared as %s, which is also how the engine names a script class"
612
- + " with no class_name; if it is one, the object given has the right class and another"
613
- + " script: it is %s"
652
+ ". The parameter is declared as %s, which is also how the engine names a "
653
+ + "script class with no class_name; if it is one, the object given has the "
654
+ + "right class and another script: it is %s"
614
655
  )
615
656
  % checked
616
657
  )
617
- return {"type": "error", "message": message + "."}
658
+ return { "type": "error", "message": message + "." }
618
659
 
619
660
  var answer: Dictionary = {
620
661
  "type": "method_result",
621
662
  "path": node_path,
622
663
  "method": method,
623
664
  "result": _values.serialize(result),
624
- "elapsed_usec": elapsed
665
+ "elapsed_usec": elapsed,
625
666
  }
626
667
  if awaited:
627
668
  answer["awaited"] = true
@@ -629,7 +670,8 @@ func call_method(params: Dictionary) -> Dictionary:
629
670
  answer["outside_declared"] = " ".join(outside)
630
671
  _keep_reported(answer, "errors", caught.raised)
631
672
  _keep_reported(answer, "warnings", caught.warned)
632
- # Main.explode, ended at a null it called into, answered result 0 as if it had counted something.
673
+ # Main.explode, ended at a null it called into, answered result 0 as if it had counted
674
+ # something.
633
675
  if caught.ended_at.has(named):
634
676
  answer["ended_by_error_at"] = caught.ended_at[named]
635
677
  var asked: Variant = params.get("properties")
@@ -648,9 +690,9 @@ static func _keep_reported(answer: Dictionary, field: String, reported: Array[St
648
690
  answer[field + "_not_shown"] = reported.size() - ERRORS_KEPT
649
691
 
650
692
 
651
- ## Why [param named], the last step of a call's method, names no method of [param holder] to call, or
652
- ## "" when it does. Brackets on it holding arguments are refused rather than read: the arguments are
653
- ## taken from args alone, so a call is never made with half of them in one place and half in the
693
+ ## Why [param named], the last step of a call's method, names no method of [param holder] to call,
694
+ ## or "" when it does. Brackets on it holding arguments are refused rather than read: the arguments
695
+ ## are taken from args alone, so a call is never made with half of them in one place and half in the
654
696
  ## other, or with the bracketed ones quietly dropped.
655
697
  static func _not_a_method_to_call(holder: Object, named: String, called: String) -> String:
656
698
  var method: String = named
@@ -659,7 +701,10 @@ static func _not_a_method_to_call(holder: Object, named: String, called: String)
659
701
  var in_brackets: Array = bracketed.get("args", [])
660
702
  if bracketed.has("message") or not in_brackets.is_empty():
661
703
  return (
662
- "%s:%s: the method a call ends on takes its arguments under args, not in its brackets"
704
+ (
705
+ "%s:%s: the method a call ends on takes its arguments under args, not in its "
706
+ + "brackets"
707
+ )
663
708
  % [called, named]
664
709
  )
665
710
  method = GdhPaths.method_of(named)
@@ -675,12 +720,15 @@ static func _instance_method(holder: Object, method: String, called: String) ->
675
720
  return ""
676
721
  var script: Script = holder
677
722
  for entry: Dictionary in script.get_script_method_list():
678
- if str(entry.get("name", "")) != method or GdhRead.as_int(entry.get("flags", 0)) & METHOD_FLAG_STATIC:
723
+ if (
724
+ str(entry.get("name", "")) != method
725
+ or GdhRead.as_int(entry.get("flags", 0)) & METHOD_FLAG_STATIC
726
+ ):
679
727
  continue
680
728
  return (
681
729
  (
682
- "%s.%s is not static, so it runs on an instance of the class: call it on a node carrying %s,"
683
- + " or on an object a path from one reaches"
730
+ "%s.%s is not static, so it runs on an instance of the class: call it on a node "
731
+ + "carrying %s, or on an object a path from one reaches"
684
732
  )
685
733
  % [called, method, script.resource_path]
686
734
  )
@@ -726,21 +774,25 @@ func _read_off_result(result: Variant, asked: Variant) -> Dictionary:
726
774
  read_by_key[str(key)] = got
727
775
  else:
728
776
  entries.append([shown, got])
729
- var shaped: Variant = read_by_key if texts else {"_type": "Dictionary", "entries": entries}
777
+ var shaped: Variant = read_by_key if texts else {
778
+ "_type": "Dictionary",
779
+ "entries": entries,
780
+ }
730
781
  return _read_off_many(shaped, map.values(), "Dictionary", missing)
731
782
  if result is Object and not is_instance_valid(result):
732
783
  return {
733
- "properties_note": "the call answered an object that has since been freed, so nothing was read"
784
+ "properties_note":
785
+ "the call answered an object that has since been freed, so nothing was read",
734
786
  }
735
787
  if not result is Object:
736
788
  return {
737
789
  "properties_note":
738
- "the call answered %s, which has no properties to read" % type_string(typeof(result))
790
+ "the call answered %s, which has no properties to read" % type_string(typeof(result)),
739
791
  }
740
792
  var object: Object = result
741
793
  var one: Dictionary = _read_off_object(object, asked)
742
794
  missing = one["missing"]
743
- var answered: Dictionary = {"result_properties": one["read"]}
795
+ var answered: Dictionary = { "result_properties": one["read"] }
744
796
  if not missing.is_empty():
745
797
  answered["result_properties_missing"] = missing
746
798
  return answered
@@ -748,7 +800,9 @@ func _read_off_result(result: Variant, asked: Variant) -> Dictionary:
748
800
 
749
801
  ## What was read off one element of a list or a dictionary a call answered with, or null for one
750
802
  ## that is no object; why a name was not there goes into [param missing], led by [param named].
751
- func _read_off_element(element: Variant, named: String, asked: Variant, missing: Array[String]) -> Variant:
803
+ func _read_off_element(
804
+ element: Variant, named: String, asked: Variant, missing: Array[String]
805
+ ) -> Variant:
752
806
  if not element is Object:
753
807
  return null
754
808
  if not is_instance_valid(element):
@@ -770,9 +824,9 @@ static func _read_off_many(
770
824
  if not elements.any(func(element: Variant) -> bool: return element is Object):
771
825
  return {
772
826
  "properties_note":
773
- "the call answered %s with no object in it, so there are no properties to read" % shape
827
+ "the call answered %s with no object in it, so there are no properties to read" % shape,
774
828
  }
775
- var answered: Dictionary = {"result_properties": read}
829
+ var answered: Dictionary = { "result_properties": read }
776
830
  if not missing.is_empty():
777
831
  answered["result_properties_missing"] = missing
778
832
  return answered
@@ -795,7 +849,7 @@ func _read_off_object(object: Object, asked: Variant) -> Dictionary:
795
849
  missing.append(str(walked["message"]))
796
850
  else:
797
851
  read[path] = _values.serialize(walked["value"])
798
- return {"read": read, "missing": missing}
852
+ return { "read": read, "missing": missing }
799
853
 
800
854
 
801
855
  ## The variables the script attached to [param object] declares, in the order it declares them.
@@ -817,13 +871,16 @@ static func _walk_from(object: Object, path: String) -> Dictionary:
817
871
  if not GdhPaths.can_hold(holder):
818
872
  return {
819
873
  "message":
820
- "%s holds %s, which has nothing to read %s off" % [called, type_string(typeof(holder)), named]
874
+ (
875
+ "%s holds %s, which has nothing to read %s off"
876
+ % [called, type_string(typeof(holder)), named]
877
+ ),
821
878
  }
822
879
  if not GdhPaths.can_read(holder, named):
823
- return {"message": GdhPaths.nothing_there(holder, named, called)}
880
+ return { "message": GdhPaths.nothing_there(holder, named, called) }
824
881
  holder = GdhPaths.read_under(holder, named)
825
882
  called = "%s:%s" % [called, named]
826
- return {"value": holder}
883
+ return { "value": holder }
827
884
 
828
885
 
829
886
  ## Why [param given] arguments are the wrong number for [param method], or "" when they are not.
@@ -832,8 +889,9 @@ static func _walk_from(object: Object, path: String) -> Dictionary:
832
889
  ## null, and the method list says how many a method takes: its parameters less those with defaults,
833
890
  ## up to all of them, or any number past that for one taking varargs.
834
891
  static func _argument_count_refused(holder: Object, method: String, given: int) -> String:
835
- # A node's method list runs to hundreds of entries, and walking it costs a couple of milliseconds
836
- # of the game's frame; a call giving exactly the arguments the method declares needs no walk.
892
+ # A node's method list runs to hundreds of entries, and walking it costs a couple of
893
+ # milliseconds of the game's frame; a call giving exactly the arguments the method declares
894
+ # needs no walk.
837
895
  if given == holder.get_method_argument_count(method):
838
896
  return ""
839
897
  for entry: Dictionary in GdhValues.methods_of(holder):
@@ -856,8 +914,8 @@ static func _argument_count_refused(holder: Object, method: String, given: int)
856
914
  return ""
857
915
 
858
916
 
859
- ## [method _object_named] with the path first, which is the order [method GdhValues.typed_like] calls
860
- ## an element resolver in.
917
+ ## [method _object_named] with the path first, which is the order [method GdhValues.typed_like]
918
+ ## calls an element resolver in.
861
919
  func _element_object(
862
920
  given: Variant, declared: String, script: Script, node: Node, node_path: String
863
921
  ) -> Dictionary:
@@ -886,7 +944,7 @@ func _object_named(
886
944
  node: Node, node_path: String, given: Variant, declared: String, script: Script = null
887
945
  ) -> Dictionary:
888
946
  if names_no_object(given):
889
- return {"object": null}
947
+ return { "object": null }
890
948
  var found: Dictionary = GdhPaths.object_at(_host.get_tree().root, node, node_path, given)
891
949
  if found.has("message"):
892
950
  return found
@@ -895,9 +953,13 @@ func _object_named(
895
953
  var wanted: String = "an instance of %s" % GdhValues.script_named(script)
896
954
  if not script.get_global_name().is_empty():
897
955
  wanted = "a %s" % script.get_global_name()
898
- return {"message": "%s is %s, not %s" % [str(given), GdhValues.class_of(instance), wanted]}
956
+ return {
957
+ "message": "%s is %s, not %s" % [str(given), GdhValues.class_of(instance), wanted],
958
+ }
899
959
  if script == null and not declared.is_empty() and not GdhValues.is_a(instance, declared):
900
- return {"message": "%s is %s, not a %s" % [str(given), GdhValues.class_of(instance), declared]}
960
+ return {
961
+ "message": "%s is %s, not a %s" % [str(given), GdhValues.class_of(instance), declared],
962
+ }
901
963
  return found
902
964
 
903
965