Files
daddy 8822a03f53 Add ScriptBehavior DSL: data-driven, non-Turing-complete UGC scripting
Implements the DSL that docs/architecture/scripting_sandbox.md recommends
as the primary (and, for now, sufficient) approach in place of running
untrusted GDScript in-process: a fixed set of trigger/condition/action
verbs, expressed as plain JSON data, interpreted by trusted GDScript with
zero ability to reference engine singletons, call arbitrary methods, or
execute code.

- ScriptBehavior (scripts/scripting/script_behavior.gd): parses and
  validates rules from JSON/Dictionary data. Every trigger, condition
  type/op, and verb is checked against an explicit whitelist at parse
  time; malformed or unknown entries are dropped and recorded in
  rejected_rules, never partially executed. Carries an optional
  content_flags passthrough so this data type isn't hostile to future
  moderation-queue integration (docs/architecture/content_moderation.md).
- ScriptInterpreterNode (scripts/scripting/script_interpreter.gd): the
  only code that executes rules. Triggers: on_interact (proximity +
  "interact" input action), on_enter (edge-triggered Area3D overlap),
  on_touch (continuous overlap), on_timer (physics-clocked Timer). Verbs:
  give_item, play_sound, move, rotate, spawn_from_catalog, set_timer --
  each a fixed, hand-written function; verb dispatch is an explicit
  match(), never call()-by-name from data. move/rotate animate via Tween
  rather than teleporting.
- PlayerInventory (scripts/scripting/player_inventory.gd): a small
  per-player item-count stub for give_item to target, since no real
  inventory/entity-state system exists yet (M9 Economy). Attached to
  scenes/player.tscn as "Inventory".
- SpawnCatalog (scripts/scripting/spawn_catalog.gd): trusted catalog_id ->
  asset_id lookup for spawn_from_catalog, mirroring the AvatarCatalog
  data-driven-JSON convention. Rule data only ever supplies a catalog_id
  key, never a resource path.
- Wired a real demo ("ScriptedChest") into scenes/worlds/test_level.tscn
  with an on_interact rule (give_item + play_sound + rotate), plus an
  "interact" input action (project.godot).
- scripts/smoke_test_script_behavior.gd: exercises every trigger type,
  every verb, and every condition type against the real interpreter and
  the wired demo scene, and proves unknown/malformed/unsafe rules
  (unknown verb, unknown trigger, non-scalar smuggled arguments, etc.)
  are rejected at parse time and never run -- 50/50 checks pass.
2026-09-14 19:32:22 +00:00

9 lines
131 B
JSON

{
"templates": {
"small_crate": {
"asset_id": "props/crate_small.glb",
"display_name": "Small Crate"
}
}
}