Connect paid food purchasing, kitchen production, and porter deliveries

This commit is contained in:
Takeshi
2026-09-09 09:46:33 +09:00
parent 29a660aed0
commit 627b200f00
42 changed files with 3787 additions and 84 deletions
+58 -2
View File
@@ -48,6 +48,7 @@ var _dispatcher := TaskDispatcherType.new()
var _item_reserver := Callable()
var _item_releaser := Callable()
var _travel_estimator := Callable()
var _external_task_driver := Callable()
func configure_callbacks(
@@ -62,6 +63,49 @@ func configure_callbacks(
return self
## External operations own their work-completion transaction while retaining
## ordinary Staff movement, shifts, and bidirectional Task ownership.
func configure_external_task_driver(driver: Callable = Callable()) -> void:
_external_task_driver = driver
func is_externally_driven_task(task_id: StringName) -> bool:
return _external_task_driver.is_valid() and bool(_external_task_driver.call(task_id))
func assign_task_to_staff(task_id: StringName, staff_id: StringName, absolute_minute: int) -> CommandResult:
var task := get_task(task_id)
var staff := get_staff(staff_id)
if task == null or staff == null or not task.is_dispatchable():
return _conflict("Task or employee is unavailable for assignment.")
if not task.required_items.is_empty() or not task.reservation_ids.is_empty():
return _conflict("Explicit assignment requires externally reserved operation inputs.")
if not staff.is_available_for_dispatch() or not staff.meets_task_requirements(task):
return _conflict("Employee is busy or does not meet the Task requirements.")
if not task.reserve(staff_id, [], absolute_minute):
return _conflict("Task could not reserve its employee.")
if not staff.reserve_task(task_id, absolute_minute):
task.reopen(&"ASSIGNMENT_ROLLED_BACK", absolute_minute, true)
return _conflict("Employee could not reserve its Task.")
task_assigned.emit(task_id, staff_id)
return _success({&"task_id": task_id, &"staff_id": staff_id})
func retarget_external_task(task_id: StringName, target_cell: Vector3i, absolute_minute: int) -> CommandResult:
var task := get_task(task_id)
if task == null or not is_externally_driven_task(task_id) or task.is_terminal():
return _conflict("Only an active externally driven Task can be retargeted.")
var staff := get_staff(task.assigned_staff_id)
if staff == null or staff.current_task_id != task_id:
return _conflict("Task and employee ownership differ.")
task.target_cell = target_cell
task.state = StaffTaskType.State.MOVING
task.progress_minutes = 0
task.state_changed_at = absolute_minute
staff.transition_to(StaffRuntimeType.State.MOVING_TO_TASK, &"TASK_RETARGETED", absolute_minute)
return _success({&"task_id": task_id})
func register_staff(value: Variant) -> CommandResult:
if value == null or not value is StaffRuntime:
return _invalid("Staff runtime is missing or has an invalid type.")
@@ -678,8 +722,11 @@ func begin_task(task_id: StringName, absolute_minute: int = -1) -> CommandResult
func progress_task(
task_id: StringName,
minutes: int = 1,
absolute_minute: int = -1
absolute_minute: int = -1,
externally_driven := false
) -> CommandResult:
if is_externally_driven_task(task_id) and not externally_driven:
return _conflict("Task completion belongs to its external operation.")
var task := get_task(task_id)
if task == null:
return _not_found("Task", task_id)
@@ -755,6 +802,8 @@ func _advance_assigned_tasks(absolute_minute: int) -> Array[Dictionary]:
&"action": &"BEGAN_WORK",
})
StaffTaskType.State.WORKING:
if is_externally_driven_task(task_id):
continue
var progress_result := progress_task(task.task_id, 1, absolute_minute)
if progress_result.is_success():
actions.append({
@@ -773,8 +822,11 @@ func _advance_assigned_tasks(absolute_minute: int) -> Array[Dictionary]:
func cancel_task(
task_id: StringName,
reason: StringName = &"CANCELLED",
absolute_minute: int = -1
absolute_minute: int = -1,
externally_driven := false
) -> CommandResult:
if is_externally_driven_task(task_id) and not externally_driven:
return _conflict("External operation must release its cargo before cancellation.")
var task := get_task(task_id)
if task == null:
return _not_found("Task", task_id)
@@ -801,6 +853,8 @@ func remove_staff(
var staff := get_staff(staff_id)
if staff == null:
return _not_found("Staff", staff_id)
if is_externally_driven_task(staff.current_task_id):
return _conflict("Finish the employee external operation before removal.")
var minute := current_minute if absolute_minute < 0 else absolute_minute
if not staff.current_task_id.is_empty():
var task := get_task(staff.current_task_id)
@@ -842,6 +896,8 @@ func retire_staff(staff_id: StringName, absolute_minute: int = -1) -> CommandRes
var staff := get_staff(staff_id)
if staff == null:
return _not_found("Staff", staff_id)
if is_externally_driven_task(staff.current_task_id):
return _conflict("Finish the employee external operation before retirement.")
staff.is_retiring = true
return remove_staff(staff_id, &"RETIRED", true, absolute_minute)