extends StaticBody3D ## Cooking station. The cook timer and item conversion run only on the machine ## that owns world logic (server or offline host); `progress` is replicated to ## clients for UI via a MultiplayerSynchronizer. This is the reference ## implementation of the reusable "station work-progress" pattern: a server-owned ## progress value advanced by an input source (here, a timer), which converts the ## held item once it reaches the threshold and spawns the result over the network. @export var cook_speed := 1.0 @onready var snap_zone: XRToolsSnapZone = $XRToolsSnapZone var item = null var progress: float = 0.0 func _ready() -> void: if snap_zone.initial_object: item = snap_zone.initial_object func convert_item(cookable: CookableItem) -> void: var old_pickable = snap_zone.picked_up_object if not old_pickable: push_warning("Hob finished cooking item, but snap zone is missing its reference") return var original_transform: Transform3D = old_pickable.global_transform # Spawn the result over the network (server) or locally (offline). var result := NetworkManager.spawn_item(cookable.turns_into.resource_path, original_transform) # Remove the cooked item (despawn replicates for spawner-managed items). snap_zone.drop_object() old_pickable.queue_free() # Snap the result into the now-empty zone. if result: snap_zone.pick_up_object(result) func _process(delta: float) -> void: # Only the world owner runs cooking logic; clients receive `progress` + the # converted item via replication. if not NetworkManager.owns_world(): return # Find the CookableItem in the held object. var cookable = null if snap_zone.picked_up_object: var matches = snap_zone.picked_up_object.get_children().filter(func(c): return c is CookableItem) if matches.size() > 0: cookable = matches[0] # Advance progress and convert once cooked. if cookable: progress += cook_speed * delta if progress >= cookable.cooking_time: progress = 0.0 convert_item(cookable) else: progress = 0.0