Files
TheTree_mock/scripts/world/route_subslot_path_adapter.gd
Takeshi b84bade045 Save The Tree implementation and acceptance work in progress
Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
2026-10-11 15:58:00 +09:00

1203 lines
44 KiB
GDScript

class_name RouteSubslotPathAdapter
extends RefCounted
## Atomic projection boundary between SpatialSubslotService ROUTE slots and
## PathService. The adapter owns projection metadata and idempotency evidence;
## both domain services remain authoritative for their own state.
const CommandResultType = preload("res://scripts/core/command_result.gd")
const SpatialSubslotServiceType = preload("res://scripts/world/spatial_subslot_service.gd")
const PathServiceType = preload("res://scripts/world/path_service.gd")
const SNAPSHOT_SCHEMA_VERSION := 1
const MAX_REQUEST_ID_LENGTH := 128
const MAX_PROCESSED_REQUESTS := 4_096
const MAX_HISTORY_CELL_REFERENCES := 262_144
const MAX_BASE_WALKABLE_CELLS := 65_536
const MAX_PROJECTED_CELLS := 131_072
const MAX_CELLS_PER_ROUTE_REQUEST := 256
const MAX_COORDINATE_ABS := 100_000
const MAX_SAFE_INTEGER := 9_007_199_254_740_991
const MAX_SNAPSHOT_DEPTH := 9
const MAX_CONTAINER_ITEMS := 131_072
const OPERATION_PLACE: StringName = &"PLACE"
const OPERATION_REPLACE: StringName = &"REPLACE"
const OPERATION_REMOVE: StringName = &"REMOVE"
const OPERATION_SYNCHRONIZE: StringName = &"SYNCHRONIZE"
const OPERATIONS: Array[StringName] = [
OPERATION_PLACE,
OPERATION_REPLACE,
OPERATION_REMOVE,
OPERATION_SYNCHRONIZE,
]
const QUARANTINE_CONFIGURE_ROLLBACK: StringName = &"CONFIGURE_ROLLBACK_UNCERTAIN"
const QUARANTINE_TRANSACTION_ROLLBACK: StringName = &"TRANSACTION_ROLLBACK_UNCERTAIN"
const QUARANTINE_REASONS: Array[StringName] = [
QUARANTINE_CONFIGURE_ROLLBACK,
QUARANTINE_TRANSACTION_ROLLBACK,
]
var source_revision := 0
var projection_revision := 0
var last_error := ""
var _source: SpatialSubslotService
var _path: PathService
var _configured := false
var _base_walkable_cells: Dictionary = {}
var _projected_route_cells: Array[Vector3i] = []
var _projected_walkable_cells: Array[Vector3i] = []
var _processed_requests: Dictionary = {}
var _quarantined := false
var _quarantine_reason: StringName = &""
var _transaction_active := false
# One private successful parse input; live graph/source checks still run each time.
var _validated_owned_snapshot: Dictionary = {}
## Binds the two authoritative services once and establishes projection 1.
## Existing primary World occupancy is intentionally not consulted: ROUTE is
## an independent subslot and is merged with the supplied base walkable cells.
func configure(
source_value: Variant,
path_value: Variant,
base_walkable_cells: Variant
) -> bool:
if _transaction_active:
return _fail("Route projection configuration cannot reenter an active transaction.")
if _configured:
return _fail("Route projection adapter is already configured.")
if not source_value is SpatialSubslotService or not path_value is PathService:
return _fail("Route projection requires SpatialSubslotService and PathService instances.")
var normalized_base := _normalize_cells(
base_walkable_cells,
true,
MAX_BASE_WALKABLE_CELLS,
"Base walkable cells"
)
if not bool(normalized_base[&"ok"]):
return _fail(String(normalized_base[&"message"]))
var source_service: SpatialSubslotService = source_value
var path_service: PathService = path_value
var source_audit: Dictionary = source_service.validate_invariants()
if not bool(source_audit.get(&"ok", false)):
return _fail("Spatial subslot source invariants are invalid.")
var route_cells := source_service.get_route_cells()
var projected := _union_cells(normalized_base[&"cells"], route_cells)
if projected.size() > MAX_PROJECTED_CELLS:
return _fail("Projected walkable-cell capacity is exceeded.")
var owned_before := _capture_owned_state()
_transaction_active = true
var guard_state := _capture_owned_state()
var source_snapshot := source_service.create_snapshot()
var path_capture := _capture_path_state(path_service)
if not bool(path_capture[&"ok"]):
_restore_owned_state(owned_before)
return _fail(String(path_capture[&"message"]))
var apply_ok := path_service.rebuild_graph(projected.duplicate())
var callback_tampered := not _owned_state_matches(guard_state)
var source_tampered := source_service.create_snapshot() != source_snapshot
var path_matches := _path_cells_match(path_service, projected)
if not apply_ok or callback_tampered or source_tampered or not path_matches:
var rollback_ok := _restore_dependencies_exact(
source_service,
path_service,
source_snapshot,
path_capture
)
_restore_owned_state(owned_before)
if not rollback_ok:
_bind_quarantined_configuration(
source_service,
path_service,
normalized_base[&"cells"],
route_cells,
projected,
QUARANTINE_CONFIGURE_ROLLBACK
)
return _fail("Route projection configuration failed and rollback is uncertain.")
return _fail(
"Route projection callback tampered with the adapter and was rolled back."
if callback_tampered or source_tampered
else "Path graph rejected the initial route projection; state was rolled back."
)
_source = source_service
_path = path_service
_configured = true
_base_walkable_cells = _cell_set(normalized_base[&"cells"])
_projected_route_cells = route_cells.duplicate()
_projected_walkable_cells = projected.duplicate()
source_revision = source_service.get_revision_for_category(source_service.CATEGORY_ROUTE)
projection_revision = 1
_processed_requests.clear()
_quarantined = false
_quarantine_reason = &""
_transaction_active = false
last_error = ""
return true
func place_route(
request_id: Variant,
entity_id: Variant,
cells: Variant
) -> CommandResult:
return _execute_route_request(OPERATION_PLACE, request_id, entity_id, cells)
func replace_route(
request_id: Variant,
entity_id: Variant,
cells: Variant
) -> CommandResult:
return _execute_route_request(OPERATION_REPLACE, request_id, entity_id, cells)
func remove_route(request_id: Variant, entity_id: Variant) -> CommandResult:
return _execute_route_request(OPERATION_REMOVE, request_id, entity_id, [])
## Reconciles direct, out-of-adapter ROUTE changes or Path topology drift. A
## supplied base set atomically replaces the prior World walkability projection.
func synchronize_projection(
request_id: Variant,
base_walkable_cells: Variant = null
) -> CommandResult:
var requested_base: Variant = (
get_base_walkable_cells() if base_walkable_cells == null else base_walkable_cells
)
return _execute_route_request(OPERATION_SYNCHRONIZE, request_id, &"", requested_base)
func is_configured() -> bool:
return _configured
## Identity-only binding check for higher-level atomic coordinators. The
## authoritative service references themselves remain encapsulated.
func is_bound_to(source_value: Variant, path_value: Variant) -> bool:
return _configured and _source == source_value and _path == path_value
func is_quarantined() -> bool:
return _quarantined
func get_quarantine_reason() -> StringName:
return _quarantine_reason
func get_base_walkable_cells(sort_result := true) -> Array[Vector3i]:
return _sorted_cells(_base_walkable_cells.keys(), sort_result)
func get_projected_route_cells() -> Array[Vector3i]:
return _projected_route_cells.duplicate()
func get_projected_walkable_cells() -> Array[Vector3i]:
return _projected_walkable_cells.duplicate()
func get_processed_request_ids() -> Array[StringName]:
return _sorted_names(_processed_requests)
func get_projection_status() -> Dictionary:
return _projection_status_internal().duplicate(true)
func is_projection_stale() -> bool:
return bool(_projection_status_internal()[&"stale"])
func create_snapshot() -> Dictionary:
if not _configured:
return {}
var request_rows: Array[Dictionary] = []
for request_id: StringName in _sorted_names(_processed_requests):
var record: Dictionary = _processed_requests[request_id]
var details: Dictionary = record[&"details"]
request_rows.append({
&"request_id": String(request_id),
&"operation": String(record[&"operation"]),
&"entity_id": String(record[&"entity_id"]),
&"input_source_revision": int(record[&"input_source_revision"]),
&"input_cells": (record[&"input_cells"] as Array).duplicate(),
&"fingerprint": String(record[&"fingerprint"]),
&"details": {
&"request_id": String(details[&"request_id"]),
&"operation": String(details[&"operation"]),
&"entity_id": String(details[&"entity_id"]),
&"cells": (details[&"cells"] as Array).duplicate(),
&"changed": bool(details[&"changed"]),
&"source_revision": int(details[&"source_revision"]),
&"projection_revision": int(details[&"projection_revision"]),
},
})
return {
&"schema_version": SNAPSHOT_SCHEMA_VERSION,
&"source_revision": source_revision,
&"projection_revision": projection_revision,
&"base_walkable_cells": get_base_walkable_cells(),
&"projected_route_cells": get_projected_route_cells(),
&"projected_walkable_cells": get_projected_walkable_cells(),
&"processed_requests": request_rows,
&"quarantined": _quarantined,
&"quarantine_reason": String(_quarantine_reason),
}
## Restores adapter-owned state only. Non-quarantined snapshots must crosslink
## exactly with the already-restored SpatialSubslotService and PathService.
func restore_snapshot(snapshot: Dictionary) -> bool:
if _transaction_active:
return _fail("Route projection snapshot cannot restore during a transaction.")
if not _configured:
return _fail("Route projection adapter must be configured before restore.")
var parsed := _parse_snapshot(snapshot)
if not bool(parsed[&"ok"]):
return _fail(String(parsed[&"message"]))
var owned_before := _capture_owned_state()
_transaction_active = true
var guard_state := _capture_owned_state()
if not bool(parsed[&"quarantined"]):
var live_matches := _live_projection_matches(
int(parsed[&"source_revision"]),
parsed[&"projected_route_cells"],
parsed[&"projected_walkable_cells"]
)
if not live_matches or not _owned_state_matches(guard_state):
_restore_owned_state(owned_before)
return _fail("Route projection snapshot does not match the live source and Path graph.")
_source_revision_from_parsed(parsed)
_transaction_active = false
last_error = ""
return true
func validate_invariants() -> Dictionary:
var errors: Array[String] = []
if not _configured or _source == null or _path == null:
errors.append("Route projection adapter is not configured.")
return {&"ok": false, &"errors": errors}
var owned_snapshot := create_snapshot()
if owned_snapshot != _validated_owned_snapshot:
var parsed := _parse_snapshot(owned_snapshot)
if not bool(parsed[&"ok"]):
errors.append(String(parsed[&"message"]))
else:
_validated_owned_snapshot = owned_snapshot
if not _quarantine_state_is_valid(_quarantined, _quarantine_reason):
errors.append("Route projection quarantine state is inconsistent.")
if not _quarantined:
var status := _projection_status_internal()
if bool(status[&"stale"]):
errors.append("Route projection crosslinks are stale.")
return {&"ok": errors.is_empty(), &"errors": errors}
func _execute_route_request(
operation: StringName,
request_id_value: Variant,
entity_id_value: Variant,
cells_value: Variant
) -> CommandResult:
if _transaction_active:
return _failure(
CommandResultType.Code.TRANSACTION_CLOSED,
"Route projection transaction is already active."
)
if not _configured:
return _failure(CommandResultType.Code.TRANSACTION_CLOSED, "Route projection adapter is not configured.")
if not _stable_id_is_valid(request_id_value):
return _failure(CommandResultType.Code.INVALID_PAYLOAD, "Route projection request ID is invalid.")
if not OPERATIONS.has(operation):
return _failure(CommandResultType.Code.INVALID_COMMAND, "Route projection operation is invalid.")
var request_id := StringName(request_id_value)
var entity_id: StringName = &""
var input_cells: Array[Vector3i] = []
var input_source_revision := -1
if operation == OPERATION_SYNCHRONIZE:
input_source_revision = _source.get_revision_for_category(_source.CATEGORY_ROUTE)
var normalized_base := _normalize_cells(
cells_value,
true,
MAX_BASE_WALKABLE_CELLS,
"Synchronization base walkable cells"
)
if not bool(normalized_base[&"ok"]):
return _failure(CommandResultType.Code.INVALID_PAYLOAD, String(normalized_base[&"message"]))
input_cells = normalized_base[&"cells"]
else:
if not _stable_id_is_valid(entity_id_value):
return _failure(CommandResultType.Code.INVALID_PAYLOAD, "Route entity ID is invalid.")
entity_id = StringName(entity_id_value)
if operation in [OPERATION_PLACE, OPERATION_REPLACE]:
var normalized := _normalize_cells(
cells_value,
false,
MAX_CELLS_PER_ROUTE_REQUEST,
"Route request cells"
)
if not bool(normalized[&"ok"]):
return _failure(CommandResultType.Code.INVALID_PAYLOAD, String(normalized[&"message"]))
input_cells = normalized[&"cells"]
var fingerprint := _request_fingerprint(
operation,
entity_id,
input_source_revision,
input_cells
)
if _processed_requests.has(request_id):
var previous: Dictionary = _processed_requests[request_id]
if String(previous[&"fingerprint"]) != fingerprint:
return _failure(
CommandResultType.Code.DUPLICATE_IDEMPOTENCY_KEY,
"Route projection request ID conflicts with earlier input."
)
var replay := _success((previous[&"details"] as Dictionary).duplicate(true))
replay.is_replay = true
return replay
if _quarantined:
return _failure(
CommandResultType.Code.TRANSACTION_CLOSED,
"Route projection adapter is quarantined until an exact snapshot is restored.",
{&"quarantine_reason": _quarantine_reason}
)
if _processed_requests.size() >= MAX_PROCESSED_REQUESTS:
return _failure(CommandResultType.Code.VALIDATION_FAILED, "Route request history capacity is exhausted.")
if _history_cell_reference_count(_processed_requests) > MAX_HISTORY_CELL_REFERENCES - input_cells.size():
return _failure(CommandResultType.Code.VALIDATION_FAILED, "Route request history cell budget is exhausted.")
var owned_before := _capture_owned_state()
_transaction_active = true
var guard_state := _capture_owned_state()
var status_before := _projection_status_internal()
if operation != OPERATION_SYNCHRONIZE and bool(status_before[&"stale"]):
_restore_owned_state(owned_before)
return _failure(
CommandResultType.Code.TRANSACTION_CLOSED,
"Route projection is stale and must be synchronized before mutation.",
status_before
)
var source_audit: Dictionary = _source.validate_invariants()
if not bool(source_audit.get(&"ok", false)):
_restore_owned_state(owned_before)
return _failure(CommandResultType.Code.VALIDATION_FAILED, "Spatial route source invariants are invalid.")
if operation in [OPERATION_REPLACE, OPERATION_REMOVE]:
if not _source.has_entity(entity_id):
_restore_owned_state(owned_before)
return _failure(CommandResultType.Code.NOT_FOUND, "Route entity was not found.")
if _source.get_entity_category(entity_id) != _source.CATEGORY_ROUTE:
_restore_owned_state(owned_before)
return _failure(CommandResultType.Code.VALIDATION_FAILED, "Adapter may mutate only ROUTE entities.")
var source_service := _source
var path_service := _path
var source_snapshot := source_service.create_snapshot()
var path_capture := _capture_path_state(path_service)
if not bool(path_capture[&"ok"]) or not _owned_state_matches(guard_state):
var capture_rollback_ok := false
if bool(path_capture[&"ok"]):
capture_rollback_ok = _restore_dependencies_exact(
source_service, path_service, source_snapshot, path_capture
)
else:
capture_rollback_ok = source_service.create_snapshot() == source_snapshot
_restore_owned_state(owned_before)
if not capture_rollback_ok:
_quarantine(QUARANTINE_TRANSACTION_ROLLBACK)
return _failure(
CommandResultType.Code.TRANSACTION_CLOSED,
"Route capture was tampered with and rollback is uncertain.",
{&"rollback_ok": false, &"quarantined": true}
)
return _failure(
CommandResultType.Code.TRANSACTION_APPLY_FAILED,
"Route transaction capture failed without changing authoritative state.",
{&"rollback_ok": true, &"quarantined": false}
)
var result_cells: Array[Vector3i] = []
var source_result: CommandResult
match operation:
OPERATION_PLACE:
result_cells = input_cells.duplicate()
source_result = source_service.place(entity_id, source_service.CATEGORY_ROUTE, input_cells)
OPERATION_REPLACE:
result_cells = input_cells.duplicate()
source_result = source_service.replace_entity_cells(entity_id, input_cells)
OPERATION_REMOVE:
result_cells = source_service.get_entity_cells(entity_id)
source_result = source_service.remove(entity_id)
OPERATION_SYNCHRONIZE:
source_result = CommandResultType.succeeded()
_:
source_result = CommandResultType.failed(CommandResultType.Code.INVALID_COMMAND, 0, "Unknown route operation.")
var callback_tampered := not _owned_state_matches(guard_state)
if not source_result.is_success() or callback_tampered:
return _rollback_transaction_failure(
owned_before,
source_service,
path_service,
source_snapshot,
path_capture,
"Spatial route apply failed." if not source_result.is_success() else "Spatial callback tampered with the route adapter."
)
var next_route_cells := source_service.get_route_cells()
var next_base_cells := (
input_cells.duplicate() if operation == OPERATION_SYNCHRONIZE else get_base_walkable_cells()
)
var next_walkable_cells := _union_cells(next_base_cells, next_route_cells)
if next_walkable_cells.size() > MAX_PROJECTED_CELLS:
return _rollback_transaction_failure(
owned_before,
source_service,
path_service,
source_snapshot,
path_capture,
"Projected walkable-cell capacity is exceeded."
)
var path_apply_ok := path_service.rebuild_graph(next_walkable_cells.duplicate())
callback_tampered = not _owned_state_matches(guard_state)
var next_source_revision := source_service.get_revision_for_category(source_service.CATEGORY_ROUTE)
var post_source_audit: Dictionary = source_service.validate_invariants()
var postcondition_ok := (
path_apply_ok
and not callback_tampered
and bool(post_source_audit.get(&"ok", false))
and source_service.get_route_cells() == next_route_cells
and _path_cells_match(path_service, next_walkable_cells)
)
if not postcondition_ok:
return _rollback_transaction_failure(
owned_before,
source_service,
path_service,
source_snapshot,
path_capture,
"Path projection failed or violated its postcondition."
)
var changed := (
bool(status_before[&"stale"]) or next_base_cells != get_base_walkable_cells()
if operation == OPERATION_SYNCHRONIZE
else bool(source_result.details.get(&"changed", true))
)
if changed:
projection_revision += 1
source_revision = next_source_revision
_base_walkable_cells = _cell_set(next_base_cells)
_projected_route_cells = next_route_cells.duplicate()
_projected_walkable_cells = next_walkable_cells.duplicate()
var details := {
&"request_id": request_id,
&"operation": operation,
&"entity_id": entity_id,
&"cells": result_cells.duplicate(),
&"changed": changed,
&"source_revision": source_revision,
&"projection_revision": projection_revision,
}
_processed_requests[request_id] = {
&"operation": operation,
&"entity_id": entity_id,
&"input_source_revision": input_source_revision,
&"input_cells": input_cells.duplicate(),
&"fingerprint": fingerprint,
&"details": details.duplicate(true),
}
_transaction_active = false
last_error = ""
return _success(details)
func _rollback_transaction_failure(
owned_before: Dictionary,
source_service: SpatialSubslotService,
path_service: PathService,
source_snapshot: Dictionary,
path_capture: Dictionary,
message: String
) -> CommandResult:
var rollback_ok := _restore_dependencies_exact(
source_service,
path_service,
source_snapshot,
path_capture
)
_restore_owned_state(owned_before)
if not rollback_ok:
_quarantine(QUARANTINE_TRANSACTION_ROLLBACK)
return _failure(
CommandResultType.Code.TRANSACTION_CLOSED,
"%s Rollback is uncertain; adapter was quarantined." % message,
{&"rollback_ok": false, &"quarantined": true, &"quarantine_reason": _quarantine_reason}
)
return _failure(
CommandResultType.Code.TRANSACTION_APPLY_FAILED,
"%s Both services were rolled back exactly." % message,
{&"rollback_ok": true, &"quarantined": false}
)
func _projection_status_internal() -> Dictionary:
if not _configured or _source == null or _path == null:
return {
&"configured": false,
&"stale": true,
&"quarantined": _quarantined,
&"quarantine_reason": _quarantine_reason,
&"source_revision": -1,
&"projected_source_revision": source_revision,
&"projection_revision": projection_revision,
&"source_changed": true,
&"path_changed": true,
}
var current_source_revision := _source.get_revision_for_category(_source.CATEGORY_ROUTE)
var current_route_cells := _source.get_route_cells()
var path_capture := _capture_path_state(_path, false)
var source_changed: bool = (
current_source_revision != source_revision
or current_route_cells != _projected_route_cells
)
var path_changed: bool = (
not bool(path_capture[&"ok"])
or path_capture[&"cells"] != _projected_walkable_cells
)
var projection_crosslink_ok: bool = (
_union_cells(get_base_walkable_cells(false), _projected_route_cells)
== _projected_walkable_cells
)
return {
&"configured": true,
&"stale": _quarantined or source_changed or path_changed or not projection_crosslink_ok,
&"quarantined": _quarantined,
&"quarantine_reason": _quarantine_reason,
&"source_revision": current_source_revision,
&"projected_source_revision": source_revision,
&"projection_revision": projection_revision,
&"source_changed": source_changed,
&"path_changed": path_changed,
}
func _live_projection_matches(
expected_source_revision: int,
expected_route_cells: Array[Vector3i],
expected_walkable_cells: Array[Vector3i]
) -> bool:
var audit: Dictionary = _source.validate_invariants()
return (
bool(audit.get(&"ok", false))
and _source.get_revision_for_category(_source.CATEGORY_ROUTE) == expected_source_revision
and _source.get_route_cells() == expected_route_cells
and _path_cells_match(_path, expected_walkable_cells)
)
func _source_revision_from_parsed(parsed: Dictionary) -> void:
source_revision = int(parsed[&"source_revision"])
projection_revision = int(parsed[&"projection_revision"])
_base_walkable_cells = _cell_set(parsed[&"base_walkable_cells"])
_projected_route_cells = (parsed[&"projected_route_cells"] as Array).duplicate()
_projected_walkable_cells = (parsed[&"projected_walkable_cells"] as Array).duplicate()
_processed_requests = (parsed[&"processed_requests"] as Dictionary).duplicate(true)
_quarantined = bool(parsed[&"quarantined"])
_quarantine_reason = parsed[&"quarantine_reason"]
func _capture_owned_state() -> Dictionary:
return {
&"source": _source,
&"path": _path,
&"configured": _configured,
&"base_walkable_cells": _base_walkable_cells.duplicate(true),
&"projected_route_cells": _projected_route_cells.duplicate(),
&"projected_walkable_cells": _projected_walkable_cells.duplicate(),
&"source_revision": source_revision,
&"projection_revision": projection_revision,
&"processed_requests": _processed_requests.duplicate(true),
&"quarantined": _quarantined,
&"quarantine_reason": _quarantine_reason,
&"transaction_active": _transaction_active,
}
func _owned_state_matches(capture: Dictionary) -> bool:
return (
_source == capture[&"source"]
and _path == capture[&"path"]
and _configured == bool(capture[&"configured"])
and _base_walkable_cells == capture[&"base_walkable_cells"]
and _projected_route_cells == capture[&"projected_route_cells"]
and _projected_walkable_cells == capture[&"projected_walkable_cells"]
and source_revision == int(capture[&"source_revision"])
and projection_revision == int(capture[&"projection_revision"])
and _processed_requests == capture[&"processed_requests"]
and _quarantined == bool(capture[&"quarantined"])
and _quarantine_reason == capture[&"quarantine_reason"]
and _transaction_active == bool(capture[&"transaction_active"])
)
func _restore_owned_state(capture: Dictionary) -> void:
_source = capture[&"source"]
_path = capture[&"path"]
_configured = bool(capture[&"configured"])
_base_walkable_cells = (capture[&"base_walkable_cells"] as Dictionary).duplicate(true)
_projected_route_cells.assign(capture[&"projected_route_cells"])
_projected_walkable_cells.assign(capture[&"projected_walkable_cells"])
source_revision = int(capture[&"source_revision"])
projection_revision = int(capture[&"projection_revision"])
_processed_requests = (capture[&"processed_requests"] as Dictionary).duplicate(true)
_quarantined = bool(capture[&"quarantined"])
_quarantine_reason = capture[&"quarantine_reason"]
_transaction_active = bool(capture[&"transaction_active"])
func _bind_quarantined_configuration(
source_service: SpatialSubslotService,
path_service: PathService,
base_cells: Array[Vector3i],
route_cells: Array[Vector3i],
projected_cells: Array[Vector3i],
reason: StringName
) -> void:
_source = source_service
_path = path_service
_configured = true
_base_walkable_cells = _cell_set(base_cells)
_projected_route_cells = route_cells.duplicate()
_projected_walkable_cells = projected_cells.duplicate()
source_revision = source_service.get_revision_for_category(source_service.CATEGORY_ROUTE)
projection_revision = 1
_processed_requests.clear()
_transaction_active = false
_quarantine(reason)
func _quarantine(reason: StringName) -> void:
_quarantined = true
_quarantine_reason = reason
_transaction_active = false
static func _capture_path_state(path_service: PathService, capture_snapshot := true) -> Dictionary:
var snapshot := path_service.create_snapshot()
var parsed_cells := _path_cells_from_snapshot(snapshot)
if not bool(parsed_cells[&"ok"]):
return {&"ok": false, &"message": parsed_cells[&"message"]}
for cell: Vector3i in parsed_cells[&"cells"]:
if not path_service.has_cell(cell):
return {
&"ok": false,
&"message": "Path snapshot topology has not been materialized into the live graph.",
}
var result := {&"ok": true}
if capture_snapshot:
result[&"snapshot"] = snapshot.duplicate(true)
result[&"cells"] = (parsed_cells[&"cells"] as Array).duplicate()
return result
static func _path_cells_from_snapshot(snapshot: Dictionary) -> Dictionary:
var raw_rows: Variant = snapshot.get(&"cell_traffic", null)
if not raw_rows is Array or raw_rows.size() > MAX_PROJECTED_CELLS:
return {&"ok": false, &"message": "Path snapshot does not expose a bounded cell topology."}
var cells: Array[Vector3i] = []
var seen: Dictionary = {}
for raw_row: Variant in raw_rows:
if not raw_row is Dictionary:
return {&"ok": false, &"message": "Path snapshot cell topology is malformed."}
var raw_cell: Variant = raw_row.get(&"cell", raw_row.get("cell", null))
if not _cell_is_valid(raw_cell) or seen.has(raw_cell):
return {&"ok": false, &"message": "Path snapshot contains an invalid or duplicate cell."}
seen[raw_cell] = true
cells.append(raw_cell)
cells.sort_custom(_cell_less)
return {&"ok": true, &"cells": cells}
static func _path_cells_match(path_service: PathService, expected: Array[Vector3i]) -> bool:
var capture := _capture_path_state(path_service)
if not bool(capture[&"ok"]) or capture[&"cells"] != expected:
return false
for cell: Vector3i in expected:
if not path_service.has_cell(cell):
return false
return true
static func _restore_dependencies_exact(
source_service: SpatialSubslotService,
path_service: PathService,
source_snapshot: Dictionary,
path_capture: Dictionary
) -> bool:
for _attempt: int in range(2):
source_service.restore_snapshot(source_snapshot.duplicate(true))
_restore_path_once(path_service, path_capture)
if (
source_service.create_snapshot() == source_snapshot
and _path_state_matches_capture(path_service, path_capture)
):
return true
return false
static func _restore_path_once(path_service: PathService, capture: Dictionary) -> void:
var cells: Array = capture[&"cells"]
var snapshot: Dictionary = capture[&"snapshot"]
# The second rebuild materializes PathService's pending graph revision when
# the authoritative graph is empty. Calls are intentionally best-effort;
# exact equality below is the authoritative rollback verdict.
path_service.rebuild_graph(cells.duplicate())
path_service.restore_snapshot(snapshot.duplicate(true))
path_service.rebuild_graph(cells.duplicate())
static func _path_state_matches_capture(path_service: PathService, capture: Dictionary) -> bool:
return (
path_service.create_snapshot() == capture[&"snapshot"]
and _path_cells_match(path_service, capture[&"cells"])
)
static func _parse_snapshot(snapshot: Dictionary) -> Dictionary:
if not _variant_depth_is_valid(snapshot, 0):
return {&"ok": false, &"message": "Route projection snapshot depth or capacity is exceeded."}
if not _keys_match(snapshot, [
&"base_walkable_cells",
&"processed_requests",
&"projected_route_cells",
&"projected_walkable_cells",
&"projection_revision",
&"quarantine_reason",
&"quarantined",
&"schema_version",
&"source_revision",
]):
return {&"ok": false, &"message": "Route projection snapshot root fields are not canonical."}
if typeof(snapshot.get(&"schema_version", null)) != TYPE_INT \
or int(snapshot[&"schema_version"]) != SNAPSHOT_SCHEMA_VERSION:
return {&"ok": false, &"message": "Unsupported RouteSubslotPathAdapter snapshot version."}
if typeof(snapshot.get(&"source_revision", null)) != TYPE_INT \
or typeof(snapshot.get(&"projection_revision", null)) != TYPE_INT:
return {&"ok": false, &"message": "Route projection revisions must be integers."}
var next_source_revision := int(snapshot[&"source_revision"])
var next_projection_revision := int(snapshot[&"projection_revision"])
if next_source_revision < 0 or next_source_revision > MAX_SAFE_INTEGER \
or next_projection_revision < 1 or next_projection_revision > MAX_SAFE_INTEGER:
return {&"ok": false, &"message": "Route projection revisions are outside supported bounds."}
if typeof(snapshot.get(&"quarantined", null)) != TYPE_BOOL \
or typeof(snapshot.get(&"quarantine_reason", null)) not in [TYPE_STRING, TYPE_STRING_NAME]:
return {&"ok": false, &"message": "Route projection quarantine state has invalid types."}
var next_quarantined := bool(snapshot[&"quarantined"])
var next_quarantine_reason := StringName(snapshot[&"quarantine_reason"])
if not _quarantine_state_is_valid(next_quarantined, next_quarantine_reason):
return {&"ok": false, &"message": "Route projection quarantine state is inconsistent."}
var base_result := _normalize_cells(
snapshot.get(&"base_walkable_cells", null),
true,
MAX_BASE_WALKABLE_CELLS,
"Snapshot base walkable cells"
)
var route_result := _normalize_cells(
snapshot.get(&"projected_route_cells", null),
true,
SpatialSubslotServiceType.MAX_TOTAL_SLOTS,
"Snapshot projected route cells"
)
var projected_result := _normalize_cells(
snapshot.get(&"projected_walkable_cells", null),
true,
MAX_PROJECTED_CELLS,
"Snapshot projected walkable cells"
)
for result: Dictionary in [base_result, route_result, projected_result]:
if not bool(result[&"ok"]):
return result
if snapshot[&"base_walkable_cells"] != base_result[&"cells"] \
or snapshot[&"projected_route_cells"] != route_result[&"cells"] \
or snapshot[&"projected_walkable_cells"] != projected_result[&"cells"]:
return {&"ok": false, &"message": "Route projection snapshot cells are not canonically ordered."}
if _union_cells(base_result[&"cells"], route_result[&"cells"]) != projected_result[&"cells"]:
return {&"ok": false, &"message": "Route projection snapshot union crosslink is invalid."}
var raw_requests: Variant = snapshot.get(&"processed_requests", null)
if not raw_requests is Array or raw_requests.size() > MAX_PROCESSED_REQUESTS:
return {&"ok": false, &"message": "Route projection request history is malformed or too large."}
var next_requests: Dictionary = {}
var previous_request_id := ""
var history_cell_references := 0
var latest_recorded_projection_revision := 1
for raw_record: Variant in raw_requests:
var record_result := _parse_request_record(
raw_record,
next_source_revision,
next_projection_revision,
previous_request_id
)
if not bool(record_result[&"ok"]):
return record_result
var request_id: StringName = record_result[&"request_id"]
var parsed_record: Dictionary = record_result[&"record"]
history_cell_references += (parsed_record[&"input_cells"] as Array).size()
if history_cell_references > MAX_HISTORY_CELL_REFERENCES:
return {&"ok": false, &"message": "Route projection request history cell budget is exceeded."}
latest_recorded_projection_revision = max(
latest_recorded_projection_revision,
int((parsed_record[&"details"] as Dictionary)[&"projection_revision"])
)
next_requests[request_id] = parsed_record
previous_request_id = String(request_id)
if latest_recorded_projection_revision != next_projection_revision:
return {&"ok": false, &"message": "Route projection revision lacks matching request history."}
return {
&"ok": true,
&"source_revision": next_source_revision,
&"projection_revision": next_projection_revision,
&"base_walkable_cells": base_result[&"cells"],
&"projected_route_cells": route_result[&"cells"],
&"projected_walkable_cells": projected_result[&"cells"],
&"processed_requests": next_requests,
&"quarantined": next_quarantined,
&"quarantine_reason": next_quarantine_reason,
}
static func _parse_request_record(
raw_record: Variant,
current_source_revision: int,
current_projection_revision: int,
previous_request_id: String
) -> Dictionary:
if not raw_record is Dictionary or not _keys_match(raw_record, [
&"details", &"entity_id", &"fingerprint", &"input_cells",
&"input_source_revision", &"operation", &"request_id",
]):
return {&"ok": false, &"message": "Route projection request record fields are invalid."}
for field: StringName in [&"request_id", &"operation", &"entity_id", &"fingerprint"]:
if typeof(raw_record.get(field, null)) not in [TYPE_STRING, TYPE_STRING_NAME]:
return {&"ok": false, &"message": "Route projection request record string fields are invalid."}
if typeof(raw_record.get(&"input_source_revision", null)) != TYPE_INT:
return {&"ok": false, &"message": "Route projection request source revision is invalid."}
var request_id := StringName(raw_record[&"request_id"])
var request_text := String(request_id)
var operation := StringName(raw_record[&"operation"])
var entity_id := StringName(raw_record[&"entity_id"])
var input_source_revision := int(raw_record[&"input_source_revision"])
if not _stable_id_is_valid(request_id) \
or (not previous_request_id.is_empty() and request_text <= previous_request_id) \
or not OPERATIONS.has(operation):
return {&"ok": false, &"message": "Route projection request identity/order is invalid."}
if operation == OPERATION_SYNCHRONIZE:
if not entity_id.is_empty() \
or input_source_revision < 0 \
or input_source_revision > current_source_revision:
return {&"ok": false, &"message": "Synchronization request input is inconsistent."}
else:
if not _stable_id_is_valid(entity_id) or input_source_revision != -1:
return {&"ok": false, &"message": "Route mutation request input is inconsistent."}
var allow_empty := operation in [OPERATION_REMOVE, OPERATION_SYNCHRONIZE]
var maximum_cells := (
MAX_BASE_WALKABLE_CELLS
if operation == OPERATION_SYNCHRONIZE
else MAX_CELLS_PER_ROUTE_REQUEST
)
var cells_result := _normalize_cells(
raw_record.get(&"input_cells", null),
allow_empty,
maximum_cells,
"Route projection request input cells"
)
if not bool(cells_result[&"ok"]):
return cells_result
var input_cells: Array[Vector3i] = cells_result[&"cells"]
if raw_record[&"input_cells"] != input_cells \
or (operation == OPERATION_REMOVE and not input_cells.is_empty()):
return {&"ok": false, &"message": "Route projection request cells are not canonical."}
var expected_fingerprint := _request_fingerprint(
operation,
entity_id,
input_source_revision,
input_cells
)
if String(raw_record[&"fingerprint"]) != expected_fingerprint:
return {&"ok": false, &"message": "Route projection request fingerprint is invalid."}
var details_result := _parse_request_details(
raw_record.get(&"details", null),
request_id,
operation,
entity_id,
input_cells,
current_source_revision,
current_projection_revision
)
if not bool(details_result[&"ok"]):
return details_result
return {
&"ok": true,
&"request_id": request_id,
&"record": {
&"operation": operation,
&"entity_id": entity_id,
&"input_source_revision": input_source_revision,
&"input_cells": input_cells,
&"fingerprint": expected_fingerprint,
&"details": details_result[&"details"],
},
}
static func _parse_request_details(
raw_details: Variant,
request_id: StringName,
operation: StringName,
entity_id: StringName,
input_cells: Array[Vector3i],
current_source_revision: int,
current_projection_revision: int
) -> Dictionary:
if not raw_details is Dictionary or not _keys_match(raw_details, [
&"cells", &"changed", &"entity_id", &"operation", &"projection_revision",
&"request_id", &"source_revision",
]):
return {&"ok": false, &"message": "Route projection request result fields are invalid."}
if typeof(raw_details.get(&"request_id", null)) not in [TYPE_STRING, TYPE_STRING_NAME] \
or typeof(raw_details.get(&"operation", null)) not in [TYPE_STRING, TYPE_STRING_NAME] \
or typeof(raw_details.get(&"entity_id", null)) not in [TYPE_STRING, TYPE_STRING_NAME] \
or typeof(raw_details.get(&"changed", null)) != TYPE_BOOL \
or typeof(raw_details.get(&"source_revision", null)) != TYPE_INT \
or typeof(raw_details.get(&"projection_revision", null)) != TYPE_INT:
return {&"ok": false, &"message": "Route projection request result types are invalid."}
var detail_source_revision := int(raw_details[&"source_revision"])
var detail_projection_revision := int(raw_details[&"projection_revision"])
if StringName(raw_details[&"request_id"]) != request_id \
or StringName(raw_details[&"operation"]) != operation \
or StringName(raw_details[&"entity_id"]) != entity_id \
or detail_source_revision < 0 \
or detail_source_revision > current_source_revision \
or detail_projection_revision < 1 \
or detail_projection_revision > current_projection_revision:
return {&"ok": false, &"message": "Route projection request result crosslink is invalid."}
var cells_result := _normalize_cells(
raw_details.get(&"cells", null),
operation == OPERATION_SYNCHRONIZE,
MAX_CELLS_PER_ROUTE_REQUEST,
"Route projection request result cells"
)
if not bool(cells_result[&"ok"]) or raw_details[&"cells"] != cells_result[&"cells"]:
return {&"ok": false, &"message": "Route projection request result cells are invalid."}
var result_cells: Array[Vector3i] = cells_result[&"cells"]
if operation in [OPERATION_PLACE, OPERATION_REPLACE] and result_cells != input_cells:
return {&"ok": false, &"message": "Route projection request input/result cells diverge."}
if operation == OPERATION_SYNCHRONIZE and not result_cells.is_empty():
return {&"ok": false, &"message": "Synchronization result cells must be empty."}
var changed := bool(raw_details[&"changed"])
if operation in [OPERATION_PLACE, OPERATION_REMOVE] and not changed:
return {&"ok": false, &"message": "Place/remove result must record a changed projection."}
if changed and detail_projection_revision < 2:
return {&"ok": false, &"message": "Changed projection result has an invalid revision."}
return {
&"ok": true,
&"details": {
&"request_id": request_id,
&"operation": operation,
&"entity_id": entity_id,
&"cells": result_cells,
&"changed": changed,
&"source_revision": detail_source_revision,
&"projection_revision": detail_projection_revision,
},
}
static func _normalize_cells(
value: Variant,
allow_empty: bool,
maximum: int,
label: String
) -> Dictionary:
if not value is Array or value.size() > maximum or (not allow_empty and value.is_empty()):
return {&"ok": false, &"message": "%s have an invalid collection shape or capacity." % label}
var seen: Dictionary = {}
var cells: Array[Vector3i] = []
for raw_cell: Variant in value:
if not _cell_is_valid(raw_cell) or seen.has(raw_cell):
return {&"ok": false, &"message": "%s contain an invalid or duplicate cell." % label}
seen[raw_cell] = true
cells.append(raw_cell)
cells.sort_custom(_cell_less)
return {&"ok": true, &"cells": cells}
static func _cell_is_valid(value: Variant) -> bool:
if not value is Vector3i:
return false
var cell: Vector3i = value
return (
cell.z in [SpatialSubslotServiceType.LAYER_FRONT, SpatialSubslotServiceType.LAYER_BACK]
and cell.x >= -MAX_COORDINATE_ABS
and cell.x <= MAX_COORDINATE_ABS
and cell.y >= -MAX_COORDINATE_ABS
and cell.y <= MAX_COORDINATE_ABS
)
static func _cell_set(cells: Array) -> Dictionary:
var result: Dictionary = {}
for raw_cell: Variant in cells:
result[raw_cell] = true
return result
static func _union_cells(first: Array, second: Array) -> Array[Vector3i]:
var union: Dictionary = {}
for raw_cell: Variant in first:
if raw_cell is Vector3i:
union[raw_cell] = true
for raw_cell: Variant in second:
if raw_cell is Vector3i:
union[raw_cell] = true
return _sorted_cells(union.keys())
static func _sorted_cells(source: Variant, sort_result := true) -> Array[Vector3i]:
var result: Array[Vector3i] = []
if not source is Array:
return result
for raw_cell: Variant in source:
if raw_cell is Vector3i:
result.append(raw_cell)
if sort_result:
result.sort_custom(_cell_less)
return result
static func _cell_less(left: Vector3i, right: Vector3i) -> bool:
if left.y != right.y:
return left.y < right.y
if left.x != right.x:
return left.x < right.x
return left.z < right.z
static func _sorted_names(source: Dictionary) -> Array[StringName]:
var result: Array[StringName] = []
for raw_name: Variant in source:
result.append(StringName(raw_name))
result.sort_custom(_name_less)
return result
static func _history_cell_reference_count(source: Dictionary) -> int:
var total := 0
for record_value: Variant in source.values():
if record_value is Dictionary:
var cells: Variant = record_value.get(&"input_cells", [])
if cells is Array:
total += cells.size()
return total
static func _name_less(left: StringName, right: StringName) -> bool:
return String(left) < String(right)
static func _stable_id_is_valid(value: Variant) -> bool:
if typeof(value) not in [TYPE_STRING, TYPE_STRING_NAME]:
return false
var text := String(value)
if text.is_empty() or text.length() > MAX_REQUEST_ID_LENGTH:
return false
for index: int in range(text.length()):
var code := text.unicode_at(index)
var allowed := (
code >= 48 and code <= 57
or code >= 65 and code <= 90
or code >= 97 and code <= 122
or code in [45, 46, 58, 64, 95]
)
if not allowed:
return false
return true
static func _request_fingerprint(
operation: StringName,
entity_id: StringName,
input_source_revision: int,
cells: Array[Vector3i]
) -> String:
var entity_text := String(entity_id)
var canonical := "%s|%d:%s|source=%d|cells=%d|" % [
String(operation), entity_text.length(), entity_text, input_source_revision, cells.size(),
]
for cell: Vector3i in cells:
canonical += "%d,%d,%d;" % [cell.x, cell.y, cell.z]
return canonical.sha256_text()
static func _keys_match(source: Dictionary, expected: Array) -> bool:
if source.size() != expected.size():
return false
var seen: Dictionary = {}
for raw_key: Variant in source:
if typeof(raw_key) not in [TYPE_STRING, TYPE_STRING_NAME]:
return false
var key := StringName(raw_key)
if seen.has(key) or not expected.has(key):
return false
seen[key] = true
return seen.size() == expected.size()
static func _quarantine_state_is_valid(value: bool, reason: StringName) -> bool:
return (value and QUARANTINE_REASONS.has(reason)) or (not value and reason.is_empty())
static func _variant_depth_is_valid(value: Variant, depth: int) -> bool:
if depth > MAX_SNAPSHOT_DEPTH:
return false
if value is Array:
if value.size() > MAX_CONTAINER_ITEMS:
return false
for child: Variant in value:
if not _variant_depth_is_valid(child, depth + 1):
return false
elif value is Dictionary:
if value.size() > MAX_CONTAINER_ITEMS:
return false
for key: Variant in value:
if not _variant_depth_is_valid(key, depth + 1) \
or not _variant_depth_is_valid(value[key], depth + 1):
return false
elif typeof(value) in [TYPE_OBJECT, TYPE_CALLABLE, TYPE_SIGNAL, TYPE_RID]:
return false
return true
func _success(details: Dictionary = {}) -> CommandResult:
last_error = ""
return CommandResultType.succeeded(0, details)
func _failure(code: CommandResult.Code, message: String, details: Dictionary = {}) -> CommandResult:
last_error = message
return CommandResultType.failed(code, 0, message, details)
func _fail(message: String) -> bool:
last_error = message
return false