class_name Toil extends RefCounted ## A single atomic step within a Job — walk, wait, idle, etc. ## ## Save/load contract: every value in `data` MUST be JSON-safe. ## Vector2i is NOT JSON-safe in Godot 4 — tile coordinates are stored as ## "to_x"/"to_y" integer keys, never as Vector2i. get_walk_destination() ## reconstructs Vector2i on demand. ## ## Round-trip invariant: ## var t2 := Toil.from_dict(t.to_dict()) ## assert(t2.kind == t.kind and t2.done == t.done and t2.data == t.data) const KIND_WALK: StringName = &"walk" const KIND_WAIT: StringName = &"wait" const KIND_IDLE: StringName = &"idle" var kind: StringName = KIND_IDLE ## Toil-specific params — all values must be int, float, bool, String, Dict, or Array. var data: Dictionary = {} ## Set by JobRunner when this toil is complete. var done: bool = false # ── factories ──────────────────────────────────────────────────────────────── ## Walk to the given tile. Stores coords as separate ints for JSON safety. static func walk_to(tile: Vector2i) -> Toil: var t := Toil.new() t.kind = KIND_WALK t.data = { "to_x": tile.x, "to_y": tile.y, "started": false, } return t ## Pause for `n` sim ticks. static func wait_ticks(n: int) -> Toil: var t := Toil.new() t.kind = KIND_WAIT t.data = {"ticks_remaining": n} return t ## Stand idle — never completes on its own; JobRunner must cancel or replace. static func idle() -> Toil: var t := Toil.new() t.kind = KIND_IDLE t.data = {} return t # ── save / load ────────────────────────────────────────────────────────────── func to_dict() -> Dictionary: return { "kind": str(kind), "data": data.duplicate(true), "done": done, } static func from_dict(d: Dictionary) -> Toil: var t := Toil.new() t.kind = StringName(d.get("kind", str(KIND_IDLE))) t.data = (d.get("data", {}) as Dictionary).duplicate(true) t.done = d.get("done", false) return t # ── convenience ────────────────────────────────────────────────────────────── ## Rebuild Vector2i from the JSON-safe int fields. Only valid for KIND_WALK. func get_walk_destination() -> Vector2i: return Vector2i(data.get("to_x", 0), data.get("to_y", 0))