Path: Apply "!id" access to layer-crossing and no-route diagnostics
A stopped guest warp now reports CONNECTOR_UNAVAILABLE instead of GOAL_UNREACHABLE (P14-02 review r2 follow-up). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
28e3ffe146
commit
0f23d34e9f
@@ -2097,13 +2097,16 @@ func _edge_meets_vertical_policy(from_cell: Vector3i, edge: Dictionary) -> bool:
|
|||||||
or not StringName(edge[&"connector_id"]).is_empty() or edge[&"movement_type"] != MOVEMENT_WALK
|
or not StringName(edge[&"connector_id"]).is_empty() or edge[&"movement_type"] != MOVEMENT_WALK
|
||||||
|
|
||||||
|
|
||||||
func _edge_is_accessible(edge: Dictionary, allowed_access_ids: Array[StringName]) -> bool:
|
## "" is public, "id" needs id, and "!id" is open to everyone except actors
|
||||||
var required_access: StringName = edge[&"access_id"]
|
## that carry id (guest-only warp).
|
||||||
# "!id" is open to everyone except actors that carry id (guest-only warp).
|
static func _access_id_permits(required_access: StringName, allowed_access_ids: Array[StringName]) -> bool:
|
||||||
if String(required_access).begins_with("!"):
|
if String(required_access).begins_with("!"):
|
||||||
if StringName(String(required_access).substr(1)) in allowed_access_ids:
|
return StringName(String(required_access).substr(1)) not in allowed_access_ids
|
||||||
return false
|
return required_access.is_empty() or required_access in allowed_access_ids
|
||||||
elif not required_access.is_empty() and required_access not in allowed_access_ids:
|
|
||||||
|
|
||||||
|
func _edge_is_accessible(edge: Dictionary, allowed_access_ids: Array[StringName]) -> bool:
|
||||||
|
if not _access_id_permits(edge[&"access_id"], allowed_access_ids):
|
||||||
return false
|
return false
|
||||||
var connector_id: StringName = edge[&"connector_id"]
|
var connector_id: StringName = edge[&"connector_id"]
|
||||||
if connector_id.is_empty():
|
if connector_id.is_empty():
|
||||||
@@ -2190,8 +2193,7 @@ func _cell_is_temporarily_blocked(cell: Vector3i) -> bool:
|
|||||||
## Only the absence of any permitted directed crossing proves unreachable.
|
## Only the absence of any permitted directed crossing proves unreachable.
|
||||||
func _has_permitted_layer_crossing(from_layer: int, to_layer: int, allowed_access_ids: Array[StringName]) -> bool:
|
func _has_permitted_layer_crossing(from_layer: int, to_layer: int, allowed_access_ids: Array[StringName]) -> bool:
|
||||||
for connector: Dictionary in _connectors.values():
|
for connector: Dictionary in _connectors.values():
|
||||||
var access_id: StringName = connector[&"access_id"]
|
if not _access_id_permits(connector[&"access_id"], allowed_access_ids):
|
||||||
if not access_id.is_empty() and access_id not in allowed_access_ids:
|
|
||||||
continue
|
continue
|
||||||
var from_cell: Vector3i = connector[&"from"]
|
var from_cell: Vector3i = connector[&"from"]
|
||||||
var to_cell: Vector3i = connector[&"to"]
|
var to_cell: Vector3i = connector[&"to"]
|
||||||
@@ -2257,8 +2259,7 @@ func _route_exists_with_overrides(
|
|||||||
neighbor_set[neighbor] = true
|
neighbor_set[neighbor] = true
|
||||||
for connector_id: StringName in connector_ids:
|
for connector_id: StringName in connector_ids:
|
||||||
var connector: Dictionary = _connectors[connector_id]
|
var connector: Dictionary = _connectors[connector_id]
|
||||||
var required_access: StringName = connector[&"access_id"]
|
if not _access_id_permits(connector[&"access_id"], allowed_access_ids):
|
||||||
if not required_access.is_empty() and required_access not in allowed_access_ids:
|
|
||||||
continue
|
continue
|
||||||
if not allow_unavailable_connectors and not _connector_is_operational(connector):
|
if not allow_unavailable_connectors and not _connector_is_operational(connector):
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ func _write() -> void:
|
|||||||
_clock.advance_minutes(1)
|
_clock.advance_minutes(1)
|
||||||
_expect(_runtime.path_service.get_connector(ids[0])[&"operational_state"] == PathService.CONNECTOR_OUTAGE, "reserve outage stops the warp")
|
_expect(_runtime.path_service.get_connector(ids[0])[&"operational_state"] == PathService.CONNECTOR_OUTAGE, "reserve outage stops the warp")
|
||||||
_expect(_runtime.path_service.find_path(Vector3i(0, 0, 0), Vector3i(0, 2, 0)).is_empty(), "stopped warp offers no route")
|
_expect(_runtime.path_service.find_path(Vector3i(0, 0, 0), Vector3i(0, 2, 0)).is_empty(), "stopped warp offers no route")
|
||||||
|
_expect(_runtime.path_service.find_path_report(Vector3i(0, 0, 0), Vector3i(0, 2, 0))[&"reason"] == PathService.ROUTE_CONNECTOR_UNAVAILABLE, "guest sees the stopped warp as an unavailable connector")
|
||||||
ManaOutage.release(_runtime, _state, Warp.MANA_PER_TRIP - 1)
|
ManaOutage.release(_runtime, _state, Warp.MANA_PER_TRIP - 1)
|
||||||
_clock.advance_minutes(1)
|
_clock.advance_minutes(1)
|
||||||
_expect(_runtime.path_service.get_connector(ids[0])[&"operational_state"] == PathService.CONNECTOR_OUTAGE, "reserve below one fare keeps the warp closed")
|
_expect(_runtime.path_service.get_connector(ids[0])[&"operational_state"] == PathService.CONNECTOR_OUTAGE, "reserve below one fare keeps the warp closed")
|
||||||
|
|||||||
Reference in New Issue
Block a user