gdharness 1.1.21 → 1.1.23
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 +1470 -726
- package/build/godot/addons/gdharness_editor/bridge_client.gd +12 -2
- package/build/godot/addons/gdharness_editor/property_values.gd +484 -65
- package/build/godot/addons/gdharness_editor/reading.gd +17 -0
- package/build/godot/addons/gdharness_editor/scene_file.gd +229 -0
- package/build/godot/addons/gdharness_editor/scene_file.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/serialisation.gd +116 -7
- package/build/godot/addons/gdharness_editor/tool_executor.gd +10 -3
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +374 -242
- package/build/godot/addons/gdharness_editor/tools/class_tools.gd +47 -9
- package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +206 -0
- package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd.uid +1 -0
- package/build/godot/addons/gdharness_editor/tools/play_tools.gd +90 -15
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +373 -140
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +566 -472
- package/build/godot/addons/gdharness_runtime/call_errors.gd +42 -0
- package/build/godot/addons/gdharness_runtime/call_errors.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/reading.gd +17 -0
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +15 -5
- package/build/godot/addons/gdharness_runtime/runtime_capture.gd +51 -5
- package/build/godot/addons/gdharness_runtime/runtime_changes.gd +440 -0
- package/build/godot/addons/gdharness_runtime/runtime_changes.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +184 -338
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +89 -16
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +107 -343
- package/build/godot/addons/gdharness_runtime/runtime_screen.gd +13 -1
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +90 -24
- package/build/godot/addons/gdharness_runtime/runtime_typing.gd +351 -0
- package/build/godot/addons/gdharness_runtime/runtime_typing.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +92 -33
- package/build/godot/addons/gdharness_runtime/runtime_waits.gd +61 -28
- package/build/godot/addons/gdharness_runtime/serialisation.gd +116 -7
- package/build/godot/operations/audio_buses.gd +47 -11
- package/build/godot/operations/class_cache.gd +18 -2
- package/build/godot/operations/classdb_queries.gd +28 -17
- package/build/godot/operations/dependencies.gd +128 -17
- package/build/godot/operations/file_walk.gd +20 -0
- package/build/godot/operations/gdscript_analysis.gd +59 -20
- package/build/godot/operations/gdscript_authoring.gd +127 -60
- package/build/godot/operations/godot_operations.gd +24 -5
- package/build/godot/operations/import_pipeline.gd +179 -19
- package/build/godot/operations/logger.gd +2 -2
- package/build/godot/operations/plugins.gd +88 -70
- package/build/godot/operations/project_config.gd +41 -6
- package/build/godot/operations/project_diagnostics.gd +27 -11
- package/build/godot/operations/reading.gd +17 -0
- package/build/godot/operations/resource_files.gd +60 -17
- package/build/godot/operations/serialisation.gd +116 -7
- package/build/index.js +1385 -553
- package/build/keeper.js +4 -0
- package/package.json +1 -1
|
@@ -67,6 +67,9 @@ const PACKED: Array[int] = [
|
|
|
67
67
|
## The calls an empty list has nothing to answer, which the engine reports as an error when asked.
|
|
68
68
|
const NEEDS_AN_ELEMENT: Array[String] = ["front", "back", "pick_random"]
|
|
69
69
|
|
|
70
|
+
## Said after every call a path refuses for doing something rather than reading.
|
|
71
|
+
const READS_ONLY: String = ", and a path, which a wait reads every frame, only calls methods that read"
|
|
72
|
+
|
|
70
73
|
|
|
71
74
|
## What [param reaching] names something on, which is the node itself until the name has a colon
|
|
72
75
|
## in it, and the last name along that path.
|
|
@@ -198,16 +201,33 @@ static func can_read(holder: Variant, named: String) -> bool:
|
|
|
198
201
|
var map: Dictionary = holder
|
|
199
202
|
if not method_of(named).is_empty():
|
|
200
203
|
return method_of(named) in MAP_CALLS
|
|
201
|
-
return map
|
|
204
|
+
return not _key_in(map, named).is_empty()
|
|
202
205
|
if holder is Object:
|
|
203
206
|
var object: Object = holder
|
|
204
207
|
var method: String = method_of(named)
|
|
205
208
|
if not method.is_empty():
|
|
206
|
-
return
|
|
209
|
+
return call_refused(object, method, "").is_empty()
|
|
207
210
|
return _has_property(object, named)
|
|
208
211
|
return false
|
|
209
212
|
|
|
210
213
|
|
|
214
|
+
## The key of [param map] a step names, in a list of one, or an empty list when it names none.
|
|
215
|
+
##
|
|
216
|
+
## A step is text, and a map is keyed by whatever the game put in it: text, a StringName, or a
|
|
217
|
+
## number, which a map of units by id is. Keyed by 3, "3" is not a key of it, measured on 4.7.2, so a
|
|
218
|
+
## step that reads as a number is tried as one after the two spellings of text.
|
|
219
|
+
static func _key_in(map: Dictionary, named: String) -> Array:
|
|
220
|
+
var spellings: Array = [named, StringName(named)]
|
|
221
|
+
if named.is_valid_int():
|
|
222
|
+
spellings.append(int(named))
|
|
223
|
+
if named.is_valid_float():
|
|
224
|
+
spellings.append(float(named))
|
|
225
|
+
for key: Variant in spellings:
|
|
226
|
+
if map.has(key):
|
|
227
|
+
return [key]
|
|
228
|
+
return []
|
|
229
|
+
|
|
230
|
+
|
|
211
231
|
## The method a step written as a call names, "get_viewport()" being get_viewport, or "" for a
|
|
212
232
|
## step that is a name.
|
|
213
233
|
static func method_of(named: String) -> String:
|
|
@@ -228,6 +248,62 @@ static func _arguments_required(object: Object, method: String) -> int:
|
|
|
228
248
|
return -1
|
|
229
249
|
|
|
230
250
|
|
|
251
|
+
## Why a path may not call [param method] on [param object], said about [param called_as], or ""
|
|
252
|
+
## when it may.
|
|
253
|
+
##
|
|
254
|
+
## A path is read, and a wait reads it every frame, so a call in one has to be a read. The engine
|
|
255
|
+
## marks its own reading methods const and `queue_free()`, `free()` and `set_name()` not, measured on
|
|
256
|
+
## 4.7.2. A game's methods carry no such mark, so one declared `-> void` is taken at its word, as
|
|
257
|
+
## doing something and answering nothing, and one left untyped is trusted. Without this a find
|
|
258
|
+
## with property "queue_free()" freed every node it matched, and a wait on "advance_day()" called
|
|
259
|
+
## it once a frame and then reported the state it had driven the game to.
|
|
260
|
+
static func call_refused(object: Object, method: String, called_as: String) -> String:
|
|
261
|
+
var required: int = _arguments_required(object, method)
|
|
262
|
+
if required == -1:
|
|
263
|
+
return "%s has no method %s" % [called_as, method]
|
|
264
|
+
if required > 0:
|
|
265
|
+
return (
|
|
266
|
+
"%s.%s takes %d argument%s, and a path can only call a method that takes none"
|
|
267
|
+
% [called_as, method, required, "" if required == 1 else "s"]
|
|
268
|
+
)
|
|
269
|
+
var scripted: Dictionary = _script_method(object, method)
|
|
270
|
+
if not scripted.is_empty():
|
|
271
|
+
var returned: Dictionary = scripted.get("return", {})
|
|
272
|
+
var usage: int = returned.get("usage", 0)
|
|
273
|
+
var type: int = returned.get("type", TYPE_NIL)
|
|
274
|
+
if type == TYPE_NIL and usage & PROPERTY_USAGE_NIL_IS_VARIANT == 0:
|
|
275
|
+
return (
|
|
276
|
+
"%s.%s is declared -> void, so it does something rather than answering%s"
|
|
277
|
+
% [called_as, method, READS_ONLY]
|
|
278
|
+
)
|
|
279
|
+
return ""
|
|
280
|
+
if _native_flags(object, method) & METHOD_FLAG_CONST == 0:
|
|
281
|
+
return "%s.%s changes what it is called on rather than reading it%s" % [called_as, method, READS_ONLY]
|
|
282
|
+
return ""
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
## The entry a script attached to [param object] declares for [param method], or an empty one when
|
|
286
|
+
## the method is the engine's.
|
|
287
|
+
static func _script_method(object: Object, method: String) -> Dictionary:
|
|
288
|
+
var attached: Variant = object.get_script()
|
|
289
|
+
if not attached is Script:
|
|
290
|
+
return {}
|
|
291
|
+
var script: Script = attached
|
|
292
|
+
for entry: Dictionary in script.get_script_method_list():
|
|
293
|
+
if str(entry.get("name", "")) == method:
|
|
294
|
+
return entry
|
|
295
|
+
return {}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
## The flags the engine declares [param method] with on [param object].
|
|
299
|
+
static func _native_flags(object: Object, method: String) -> int:
|
|
300
|
+
for entry: Dictionary in object.get_method_list():
|
|
301
|
+
if str(entry.get("name", "")) == method:
|
|
302
|
+
var flags: int = entry.get("flags", 0)
|
|
303
|
+
return flags
|
|
304
|
+
return 0
|
|
305
|
+
|
|
306
|
+
|
|
231
307
|
## Put [param value] where [param named] points. Only ever called once [method can_read] agrees,
|
|
232
308
|
## and lists and maps are reference types, so writing into one reaches the game's own copy.
|
|
233
309
|
static func write(holder: Variant, named: String, value: Variant) -> void:
|
|
@@ -243,10 +319,7 @@ static func write(holder: Variant, named: String, value: Variant) -> void:
|
|
|
243
319
|
var map: Dictionary = holder
|
|
244
320
|
# Written back under the key it was found under, since a map keyed by StringName and one
|
|
245
321
|
# keyed by String both read the same way and a write to the wrong one adds a second entry.
|
|
246
|
-
|
|
247
|
-
map[named] = value
|
|
248
|
-
else:
|
|
249
|
-
map[StringName(named)] = value
|
|
322
|
+
map[_key_in(map, named)[0]] = value
|
|
250
323
|
return
|
|
251
324
|
var object: Object = holder
|
|
252
325
|
object.set(named, value)
|
|
@@ -265,9 +338,7 @@ static func read_under(holder: Variant, named: String) -> Variant:
|
|
|
265
338
|
return list[_index_in(named, len(holder))]
|
|
266
339
|
if holder is Dictionary:
|
|
267
340
|
var map: Dictionary = holder
|
|
268
|
-
|
|
269
|
-
return map[named]
|
|
270
|
-
return map[StringName(named)]
|
|
341
|
+
return map[_key_in(map, named)[0]]
|
|
271
342
|
var object: Object = holder
|
|
272
343
|
var method: String = method_of(named)
|
|
273
344
|
if not method.is_empty():
|
|
@@ -311,6 +382,14 @@ static func nothing_there(holder: Variant, named: String, called_as: String) ->
|
|
|
311
382
|
return container_calls_refused(called_as, "a map", container_call)
|
|
312
383
|
var map: Dictionary = holder
|
|
313
384
|
var keys: Array = map.keys()
|
|
385
|
+
# A key reading as the step and still not reached is one of a type a step cannot spell, and
|
|
386
|
+
# saying the map has no key 3 while listing 3 among its keys contradicts itself.
|
|
387
|
+
for key: Variant in keys:
|
|
388
|
+
if str(key) == named:
|
|
389
|
+
return (
|
|
390
|
+
"%s has a key that reads %s, but it is %s, which a path step cannot name"
|
|
391
|
+
% [called_as, named, type_string(typeof(key))]
|
|
392
|
+
)
|
|
314
393
|
# Eight of them, because a map keyed by something unexpected is told by the first few and a
|
|
315
394
|
# map of two hundred would bury the sentence saying which key was missing.
|
|
316
395
|
var some: Array[String] = []
|
|
@@ -323,13 +402,7 @@ static func nothing_there(holder: Variant, named: String, called_as: String) ->
|
|
|
323
402
|
var object: Object = holder
|
|
324
403
|
var method: String = method_of(named)
|
|
325
404
|
if not method.is_empty():
|
|
326
|
-
|
|
327
|
-
if required == -1:
|
|
328
|
-
return "%s has no method %s" % [called_as, method]
|
|
329
|
-
return (
|
|
330
|
-
"%s.%s takes %d argument%s, and a path can only call a method that takes none"
|
|
331
|
-
% [called_as, method, required, "" if required == 1 else "s"]
|
|
332
|
-
)
|
|
405
|
+
return call_refused(object, method, called_as)
|
|
333
406
|
# A method spelled as a property is the likeliest thing behind a name the object has no property
|
|
334
407
|
# for, and the caller is one pair of brackets away from what they meant.
|
|
335
408
|
if object.has_method(named):
|