gdharness 0.13.41 → 0.13.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.
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
extends Logger
|
|
2
|
+
|
|
3
|
+
## Every error the engine reports inside this game, written to a file beside the announcement,
|
|
4
|
+
## in the lines the engine itself prints to stderr.
|
|
5
|
+
##
|
|
6
|
+
## A game the editor plays prints to the editor's own stderr, which nobody reads: a `push_error`
|
|
7
|
+
## raised in one reached neither `editor_output` nor the run's transcript, and the run was
|
|
8
|
+
## answered clean while the game had just refused something out loud. The debug adapter relays
|
|
9
|
+
## what the game prints and not what it reports, so the report is taken where it is made, in
|
|
10
|
+
## the game, and left where the server already looks. The lines are the engine's own so the
|
|
11
|
+
## server reads them the way it reads a run it started itself.
|
|
12
|
+
|
|
13
|
+
var _path: String
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
func _init(path: String) -> void:
|
|
17
|
+
_path = path
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# The engine's own signature for a Logger, eight parameters and not this project's to shape.
|
|
21
|
+
# gdlint:ignore = function-arguments-number
|
|
22
|
+
func _log_error(
|
|
23
|
+
function: String,
|
|
24
|
+
file: String,
|
|
25
|
+
line: int,
|
|
26
|
+
code: String,
|
|
27
|
+
rationale: String,
|
|
28
|
+
_editor_notify: bool,
|
|
29
|
+
error_type: int,
|
|
30
|
+
script_backtraces: Array[ScriptBacktrace],
|
|
31
|
+
) -> void:
|
|
32
|
+
var kind: String
|
|
33
|
+
match error_type:
|
|
34
|
+
ERROR_TYPE_WARNING:
|
|
35
|
+
kind = "WARNING"
|
|
36
|
+
ERROR_TYPE_SCRIPT:
|
|
37
|
+
kind = "SCRIPT ERROR"
|
|
38
|
+
ERROR_TYPE_SHADER:
|
|
39
|
+
kind = "SHADER ERROR"
|
|
40
|
+
_:
|
|
41
|
+
kind = "ERROR"
|
|
42
|
+
var lines: Array[String] = [
|
|
43
|
+
"%s: %s" % [kind, rationale if not rationale.is_empty() else code],
|
|
44
|
+
" at: %s (%s:%d)" % [function, file, line],
|
|
45
|
+
]
|
|
46
|
+
for backtrace: ScriptBacktrace in script_backtraces:
|
|
47
|
+
lines.append(backtrace.format(3))
|
|
48
|
+
# Opened for each report rather than held, so the file is whole on disk after every one:
|
|
49
|
+
# the last error a game reports is the one a caller most needs, and the game may be gone the
|
|
50
|
+
# moment after. Nothing here may report an error of its own, which would come straight back.
|
|
51
|
+
var report: FileAccess = (
|
|
52
|
+
FileAccess.open(_path, FileAccess.READ_WRITE)
|
|
53
|
+
if FileAccess.file_exists(_path)
|
|
54
|
+
else FileAccess.open(_path, FileAccess.WRITE)
|
|
55
|
+
)
|
|
56
|
+
if report == null:
|
|
57
|
+
return
|
|
58
|
+
report.seek_end()
|
|
59
|
+
for each: String in lines:
|
|
60
|
+
# A line the disk would not take is a report lost, and nothing here may report that.
|
|
61
|
+
var _stored: bool = report.store_line(each)
|
|
62
|
+
report.close()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uid://bhvig6uq5tvey
|
|
@@ -11,6 +11,7 @@ extends Node
|
|
|
11
11
|
## id and the reply carries it back.
|
|
12
12
|
|
|
13
13
|
const Capture = preload("runtime_capture.gd")
|
|
14
|
+
const ErrorReport = preload("error_report.gd")
|
|
14
15
|
const InputCommands = preload("runtime_input.gd")
|
|
15
16
|
const Queries = preload("runtime_queries.gd")
|
|
16
17
|
const Read = preload("reading.gd")
|
|
@@ -36,6 +37,11 @@ const SCRIPT_RUNS_SETTING: String = "gdharness/runtime/serve_script_runs"
|
|
|
36
37
|
## `EDITOR_PID_VARIABLE` in the editor addon's bridge client.
|
|
37
38
|
const EDITOR_PID_VARIABLE: String = "GDHARNESS_EDITOR_PID"
|
|
38
39
|
|
|
40
|
+
## The file the engine's error reports go to, beside the announcement and named the same way,
|
|
41
|
+
## which is where the server reads them for a run the editor plays. Kept in step with
|
|
42
|
+
## `errorReportPath` in src/runtime-client.ts.
|
|
43
|
+
const ERROR_REPORT_NAME: String = "runtime-%d.log"
|
|
44
|
+
|
|
39
45
|
var values: Values = Values.new()
|
|
40
46
|
|
|
41
47
|
# The modules are members and not locals of _init, because a Callable holds its object by id
|
|
@@ -61,6 +67,9 @@ var _outgoing: Dictionary = {}
|
|
|
61
67
|
var _port: int = 0
|
|
62
68
|
var _enabled: bool = true
|
|
63
69
|
var _announcement: String = ""
|
|
70
|
+
## Held for as long as the game runs: a Logger the engine has is kept by reference, and one
|
|
71
|
+
## that goes away mid-run takes the report with it.
|
|
72
|
+
var _errors: ErrorReport
|
|
64
73
|
## Every command, by the name a request uses, as the module method that answers it.
|
|
65
74
|
var _commands: Dictionary = {}
|
|
66
75
|
|
|
@@ -98,13 +107,35 @@ func _ready() -> void:
|
|
|
98
107
|
# even be un-paused over the socket. A debug server has to stay responsive while the game
|
|
99
108
|
# is frozen, to inspect, capture, inject or resume it.
|
|
100
109
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
|
110
|
+
_report_errors()
|
|
101
111
|
_start_server()
|
|
102
112
|
|
|
103
113
|
|
|
104
114
|
func _exit_tree() -> void:
|
|
115
|
+
if _errors != null:
|
|
116
|
+
OS.remove_logger(_errors)
|
|
117
|
+
_errors = null
|
|
105
118
|
_cleanup()
|
|
106
119
|
|
|
107
120
|
|
|
121
|
+
## The engine's error reports, written to a file for the server, for a game the editor plays.
|
|
122
|
+
##
|
|
123
|
+
## Only for one the editor plays: a game the server starts itself has its stderr in the run's
|
|
124
|
+
## transcript already, and a game somebody runs from a terminal has it on the terminal. The
|
|
125
|
+
## editor's game prints to the editor's stderr, which nobody reads, and the editor's debug
|
|
126
|
+
## adapter relays what the game prints and not what it reports. Before the server starts, so
|
|
127
|
+
## a port that cannot be bound is reported there too, and whether or not the server comes up.
|
|
128
|
+
func _report_errors() -> void:
|
|
129
|
+
if not OS.get_environment(EDITOR_PID_VARIABLE).is_valid_int():
|
|
130
|
+
return
|
|
131
|
+
var directory: String = _announcement_directory()
|
|
132
|
+
var made: Error = DirAccess.make_dir_recursive_absolute(directory)
|
|
133
|
+
if made != OK and made != ERR_ALREADY_EXISTS:
|
|
134
|
+
return
|
|
135
|
+
_errors = ErrorReport.new(directory.path_join(ERROR_REPORT_NAME % OS.get_process_id()))
|
|
136
|
+
OS.add_logger(_errors)
|
|
137
|
+
|
|
138
|
+
|
|
108
139
|
func _process(_delta: float) -> void:
|
|
109
140
|
if not _enabled or _server == null:
|
|
110
141
|
return
|