P08-03-RTPREVIEW: P08-03を閉じるための共有配置プレビュー判定
This commit is contained in:
@@ -7573,18 +7573,38 @@ func _execute_leave_facility_queue(command: SimulationCommand) -> CommandResult:
|
||||
return CommandResult.failed(CommandResult.Code.TRANSACTION_APPLY_FAILED, command.command_id, failure_message)
|
||||
return CommandResult.succeeded(command.command_id, {&"request_id": request_id, &"reason": &"GUEST_LEFT"})
|
||||
|
||||
func _execute_build_facility(command: SimulationCommand) -> CommandResult:
|
||||
var operations_gate := _operations_construction_investment_gate(command.command_id)
|
||||
func preview_build_facility(definition_id: StringName, origin: Vector3i, rotation: int) -> Dictionary:
|
||||
var definition := definition_registry.get_facility(definition_id)
|
||||
var failure := _build_facility_precheck(0, {&"definition_id": definition_id, &"origin": origin, &"rotation": rotation})
|
||||
if failure != null and definition == null:
|
||||
var code := String(failure.details.get(&"reason", CommandResult.Code.keys()[failure.code]))
|
||||
return {&"can_build": false, &"error_codes": [code],
|
||||
&"reasons": [{&"code": code, &"message": failure.message, &"cells": [], &"details": failure.details.duplicate(true)}],
|
||||
&"cells": []}
|
||||
var report: Dictionary = construction_service.validate_placement(definition, origin, rotation).to_dictionary()
|
||||
if failure != null:
|
||||
report[&"can_build"] = false
|
||||
var code := String(failure.details.get(&"reason", CommandResult.Code.keys()[failure.code]))
|
||||
var codes: Array = Array(report.get(&"error_codes", []))
|
||||
var reasons: Array = Array(report.get(&"reasons", []))
|
||||
codes.push_front(code)
|
||||
reasons.push_front({&"code": code, &"message": failure.message, &"cells": [], &"details": failure.details.duplicate(true)})
|
||||
report[&"error_codes"] = codes
|
||||
report[&"reasons"] = reasons
|
||||
return report
|
||||
|
||||
func _build_facility_precheck(command_id: int, payload: Dictionary) -> CommandResult:
|
||||
var operations_gate := _operations_construction_investment_gate(command_id)
|
||||
if operations_gate != null:
|
||||
return operations_gate
|
||||
var definition_id := StringName(command.payload.get(&"definition_id", command.payload.get("definition_id", "")))
|
||||
var definition_id := StringName(payload.get(&"definition_id", payload.get("definition_id", "")))
|
||||
var definition := definition_registry.get_facility(definition_id)
|
||||
if definition == null:
|
||||
return CommandResult.failed(CommandResult.Code.NOT_FOUND, command.command_id, "Facility definition was not found.")
|
||||
return CommandResult.failed(CommandResult.Code.NOT_FOUND, command_id, "Facility definition was not found.")
|
||||
if _facility_definition_is_unsupported_vertical_proxy(definition):
|
||||
return CommandResult.failed(
|
||||
CommandResult.Code.VALIDATION_FAILED,
|
||||
command.command_id,
|
||||
command_id,
|
||||
"Vertical infrastructure topology is not supported.",
|
||||
{
|
||||
&"reason": FacilityInfrastructureProjector.REASON_UNSUPPORTED_VERTICAL_TOPOLOGY,
|
||||
@@ -7592,18 +7612,28 @@ func _execute_build_facility(command: SimulationCommand) -> CommandResult:
|
||||
&"unchanged": true,
|
||||
}
|
||||
)
|
||||
var origin_value: Variant = _parse_world_cell(command.payload.get(&"origin", command.payload.get("origin", null)))
|
||||
var origin_value: Variant = _parse_world_cell(payload.get(&"origin", payload.get("origin", null)))
|
||||
if origin_value == null:
|
||||
return CommandResult.failed(CommandResult.Code.INVALID_PAYLOAD, command.command_id, "origin must be Vector3i or [x, y, layer].")
|
||||
return CommandResult.failed(CommandResult.Code.INVALID_PAYLOAD, command_id, "origin must be Vector3i or [x, y, layer].")
|
||||
var origin: Vector3i = origin_value
|
||||
if definition.id in [&"guest_stairs", &"service_stairs"] and not path_service.has_cell(origin + Vector3i(0, -1, 0)):
|
||||
return _staff_assignment_failure(command.command_id, &"STAIR_LANDING_MISSING", "先に階段の一つ下の階に通路を作ってください。")
|
||||
return _staff_assignment_failure(command_id, &"STAIR_LANDING_MISSING", "先に階段の一つ下の階に通路を作ってください。")
|
||||
for shaft: Dictionary in elevators.get_report()[&"shafts"]:
|
||||
if _elevator_touches_module(shaft, definition, origin) and _elevator_shaft_busy(shaft):
|
||||
return _staff_assignment_failure(command.command_id, &"ELEVATOR_BUSY", "Wait until the shaft is idle before extending it.")
|
||||
var rotation := int(command.payload.get(&"rotation", command.payload.get("rotation", 0)))
|
||||
return _staff_assignment_failure(command_id, &"ELEVATOR_BUSY", "Wait until the shaft is idle before extending it.")
|
||||
var rotation := int(payload.get(&"rotation", payload.get("rotation", 0)))
|
||||
if rotation not in definition.allowed_rotations:
|
||||
return CommandResult.failed(CommandResult.Code.INVALID_PAYLOAD, command.command_id, "The selected rotation is not allowed.")
|
||||
return CommandResult.failed(CommandResult.Code.INVALID_PAYLOAD, command_id, "The selected rotation is not allowed.")
|
||||
return null
|
||||
|
||||
func _execute_build_facility(command: SimulationCommand) -> CommandResult:
|
||||
var failure := _build_facility_precheck(command.command_id, command.payload)
|
||||
if failure != null:
|
||||
return failure
|
||||
var definition_id := StringName(command.payload.get(&"definition_id", command.payload.get("definition_id", "")))
|
||||
var definition := definition_registry.get_facility(definition_id)
|
||||
var origin: Vector3i = _parse_world_cell(command.payload.get(&"origin", command.payload.get("origin", null)))
|
||||
var rotation := int(command.payload.get(&"rotation", command.payload.get("rotation", 0)))
|
||||
var result := construction_service.start_construction(
|
||||
definition,
|
||||
origin,
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
extends SceneTree
|
||||
|
||||
var _checks := 0
|
||||
var _failures := 0
|
||||
var _serial := 0
|
||||
var _runtime: GatedRuntime
|
||||
var _clock: Variant
|
||||
var _state: Variant
|
||||
|
||||
# Seed diagnostic switches isolate precedence; the operations gate itself is real.
|
||||
class GatedRuntime extends SimulationRuntimeService:
|
||||
var block_operations := false
|
||||
var block_vertical := false
|
||||
func _operations_total_arrears() -> int:
|
||||
return 1 if block_operations else super._operations_total_arrears()
|
||||
func _facility_definition_is_unsupported_vertical_proxy(definition: Variant) -> bool:
|
||||
return block_vertical or super._facility_definition_is_unsupported_vertical_proxy(definition)
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
func _run() -> void:
|
||||
_runtime = GatedRuntime.new()
|
||||
_clock = load("res://autoload/game_clock.gd").new()
|
||||
_state = load("res://autoload/game_state.gd").new()
|
||||
_reset()
|
||||
var cell := Vector3i(-8, 2, 0)
|
||||
_failure_case(&"unknown.preview.definition", cell, 0, "NOT_FOUND", "Facility definition was not found.")
|
||||
check(_runtime.enable_production_operations().get(&"ok", false), "enable real operations gate")
|
||||
_runtime.block_operations = true
|
||||
_runtime.block_vertical = true
|
||||
_failure_case(&"unknown.preview.definition", cell, 999, "UNPAID_EXPENSES", "Operations currently block construction and investment.")
|
||||
_failure_case(&"guest_stairs", cell, 999, "UNPAID_EXPENSES", "Operations currently block construction and investment.")
|
||||
_runtime.block_operations = false
|
||||
_failure_case(&"guest_stairs", cell, 999, String(FacilityInfrastructureProjector.REASON_UNSUPPORTED_VERTICAL_TOPOLOGY), "Vertical infrastructure topology is not supported.")
|
||||
_reset()
|
||||
_failure_case(&"guest_stairs", cell, 999, "STAIR_LANDING_MISSING", "先に階段の一つ下の階に通路を作ってください。")
|
||||
_failure_case(&"guest_corridor", cell, 999, "INVALID_PAYLOAD", "The selected rotation is not allowed.")
|
||||
# origin INVALID_PAYLOAD cannot be reached through preview's Vector3i API.
|
||||
# Diagnostic landing path from the seed; existing reception provides support.
|
||||
var walkable: Array[Vector3i] = _runtime.world_service.get_walkable_cells()
|
||||
walkable.append(Vector3i(-8, 1, 0))
|
||||
check(_runtime.path_service.rebuild_graph(walkable), "diagnostic landing path")
|
||||
var report := _pure_preview(&"guest_stairs", cell, 0)
|
||||
var accepted := _command(&"guest_stairs", cell, 0)
|
||||
check(report[&"can_build"] and accepted.is_success(), "positive landing preview and command agree")
|
||||
_reset()
|
||||
check(_command(&"guest_elevator", Vector3i.ZERO, 0).is_success(), "build real elevator")
|
||||
_clock.advance_minutes(310)
|
||||
check(_runtime.submit_command(&"hire_staff_candidate", {&"candidate_id": &"staff_akane"}).is_success(), "hire elevator actor")
|
||||
var access: Array[StringName] = [&"staff"]
|
||||
var queued: Dictionary = _runtime.elevators.request_trip(&"staff:staff_akane", Vector3i.ZERO, Vector3i(0, 1, 0), _clock.absolute_minute, access)
|
||||
check(queued.get(&"ok", false), "queue real elevator trip")
|
||||
_failure_case(&"guest_elevator", Vector3i(0, 2, 0), 999, "ELEVATOR_BUSY", "Wait until the shaft is idle before extending it.")
|
||||
_runtime.free()
|
||||
_clock.free()
|
||||
_state.free()
|
||||
print("Runtime build preview: %d checks, %d failures" % [_checks, _failures])
|
||||
quit(1 if _failures > 0 else 0)
|
||||
|
||||
func _reset() -> void:
|
||||
_runtime.block_operations = false
|
||||
_runtime.block_vertical = false
|
||||
_clock.reset(1, 6, 0)
|
||||
_state.reset()
|
||||
check(_runtime.initialize(_clock, _state, 90416)[&"valid"], "initialize preview fixture")
|
||||
_runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
|
||||
_clock.set_paused(true)
|
||||
|
||||
func _pure_preview(id: StringName, cell: Vector3i, rotation: int) -> Dictionary:
|
||||
var before := var_to_bytes(_runtime.create_snapshot())
|
||||
# CommandQueue contains the accepted command log and processed receipts.
|
||||
var log_before := var_to_bytes(_runtime.command_queue.create_snapshot())
|
||||
var commands_before := _runtime.command_queue.get_accepted_command_metadata().size()
|
||||
var processed_before := _runtime.command_queue.processed_count()
|
||||
var events_before := _runtime.domain_events.recent_events().size()
|
||||
var report := _runtime.preview_build_facility(id, cell, rotation)
|
||||
check(before == var_to_bytes(_runtime.create_snapshot()), "preview preserves typed snapshot bytes")
|
||||
check(log_before == var_to_bytes(_runtime.command_queue.create_snapshot()), "preview preserves command log bytes")
|
||||
check(commands_before == _runtime.command_queue.get_accepted_command_metadata().size() and processed_before == _runtime.command_queue.processed_count(), "preview preserves command counts")
|
||||
check(events_before == _runtime.domain_events.recent_events().size(), "preview preserves event count")
|
||||
return report
|
||||
|
||||
func _failure_case(id: StringName, cell: Vector3i, rotation: int, code: String, message: String) -> void:
|
||||
var report := _pure_preview(id, cell, rotation)
|
||||
check(not report[&"can_build"] and report[&"error_codes"][0] == code, "preview first code: " + code)
|
||||
check(report[&"reasons"][0][&"code"] == code and report[&"reasons"][0][&"message"] == message, "preview real message: " + code)
|
||||
var refused := _command(id, cell, rotation)
|
||||
var command_code := String(refused.details.get(&"reason", CommandResult.Code.keys()[refused.code]))
|
||||
check(not refused.is_success() and command_code == code, "submit code agrees: " + code)
|
||||
check(refused.message == message and refused.message == report[&"reasons"][0][&"message"], "submit message agrees: " + code)
|
||||
check(refused.details == report[&"reasons"][0][&"details"], "submit details agree: " + code)
|
||||
if _runtime.definition_registry.get_facility(id) == null:
|
||||
check(report.size() == 4 and report[&"cells"].is_empty() and report[&"reasons"].size() == 1 and report[&"error_codes"].size() == 1, "unknown definition returns only precheck summary")
|
||||
|
||||
func _command(id: StringName, cell: Vector3i, rotation: int) -> CommandResult:
|
||||
_serial += 1
|
||||
return _runtime.submit_command(&"build_facility", {&"definition_id": id, &"origin": cell, &"rotation": rotation}, &"manager", &"", 0, -1, StringName("runtime.preview.%d" % _serial))
|
||||
|
||||
func check(ok: bool, message: String) -> void:
|
||||
_checks += 1
|
||||
if not ok:
|
||||
_failures += 1
|
||||
push_error(message)
|
||||
@@ -0,0 +1 @@
|
||||
uid://dqx7m2k8n4vsa
|
||||
Reference in New Issue
Block a user