58 lines
3.0 KiB
GDScript
58 lines
3.0 KiB
GDScript
@tool
|
|
extends RefCounted
|
|
|
|
## Runtime builder for the `extends Logger` scripts in `runtime/loggers/`.
|
|
##
|
|
## `Logger` is a Godot 4.5+ class. A `.gd` file that statically declares
|
|
## `extends Logger` is rejected by the parser on Godot < 4.5 — and Godot's
|
|
## editor filesystem scan parses *every* `.gd` under the project, so just
|
|
## shipping `editor_logger.gd` / `game_logger.gd` printed two
|
|
## `Parse Error: Could not find base class "Logger"` lines on every 4.3/4.4
|
|
## editor startup (#475 follow-up). They were functionally harmless (the
|
|
## scripts are only ever instanced behind a `ClassDB.class_exists("Logger")`
|
|
## gate) but they were real red error text we shouldn't ship.
|
|
##
|
|
## Fix: the two logger scripts live in `runtime/loggers/`, which carries a
|
|
## `.gdignore` so the editor scan skips the folder entirely — no parse, no
|
|
## error, on any engine. This loader reads the source off disk with
|
|
## `FileAccess` (unaffected by `.gdignore`, which only governs the resource
|
|
## importer) and compiles it at runtime via `GDScript.new()`. Callers gate
|
|
## on `ClassDB.class_exists("Logger")` first, so `build()` only ever runs on
|
|
## 4.5+, where `extends Logger` resolves cleanly.
|
|
##
|
|
## This script itself does NOT extend Logger, so it parses on every engine
|
|
## and is safe to `preload` from `plugin.gd` and `game_helper.gd`.
|
|
|
|
const EDITOR_LOGGER_PATH := "res://addons/godot_ai/runtime/loggers/editor_logger.gd"
|
|
const GAME_LOGGER_PATH := "res://addons/godot_ai/runtime/loggers/game_logger.gd"
|
|
const VALIDATION_LOGGER_PATH := "res://addons/godot_ai/runtime/loggers/validation_logger.gd"
|
|
|
|
|
|
## Compile a `.gdignore`'d logger script from its on-disk source. Returns the
|
|
## ready-to-instance GDScript, or null if the file is missing (e.g. excluded
|
|
## from an exported game) or fails to compile. Callers must already have
|
|
## confirmed `ClassDB.class_exists("Logger")` — building an `extends Logger`
|
|
## script on an engine without the class will fail the reload() and return
|
|
## null, which the gated callers treat as "logging unavailable".
|
|
static func build(path: String) -> GDScript:
|
|
if not FileAccess.file_exists(path):
|
|
return null
|
|
var source := FileAccess.get_file_as_string(path)
|
|
if source.is_empty():
|
|
return null
|
|
var script := GDScript.new()
|
|
script.source_code = source
|
|
## Deliberately do NOT set `script.resource_path`: this builds a fresh
|
|
## anonymous GDScript every call, and a reload cycle (editor_reload_plugin,
|
|
## self-update disable→enable) calls build() again for the same path. Two
|
|
## live Resources sharing one non-empty resource_path trips Godot's
|
|
## "Another resource is loaded from path ..." error and leaves the new
|
|
## script with an empty path anyway — re-introducing red console text on
|
|
## every reload, the exact thing this folder's .gdignore set out to remove.
|
|
## game_helper.gd::_handle_eval compiles from source the same way and also
|
|
## omits resource_path. The script still resolves its absolute preloads /
|
|
## class_names fine without a path.
|
|
if script.reload() != OK:
|
|
return null
|
|
return script
|