diff --git a/Stations/Counter.tscn b/Stations/Counter.tscn index ab512a8..1972882 100644 --- a/Stations/Counter.tscn +++ b/Stations/Counter.tscn @@ -1,32 +1,10 @@ [gd_scene format=3 uid="uid://efaec6ymgabo"] -[ext_resource type="PackedScene" uid="uid://cvucwxibtol5f" path="res://stations/StationMovement.tscn" id="1_3jbl6"] -[ext_resource type="Script" uid="uid://cquqe4f1m1sw6" path="res://addons/godot-xr-tools/objects/snap_zone.gd" id="1_dlkho"] +[ext_resource type="PackedScene" uid="uid://cbs8jiqe8rcmn" path="res://abstract/station.tscn" id="1_station"] [ext_resource type="Script" uid="uid://cql13y8da4auf" path="res://stations/counter.gd" id="1_oapbh"] [ext_resource type="AudioStream" uid="uid://bqtk1adk8umbx" path="res://sounds/220197__gameaudio__click-basic.wav" id="2_0aadn"] [ext_resource type="AudioStream" uid="uid://daiv8ubwdbidf" path="res://sounds/220195__gameaudio__click-wooden-1.wav" id="2_lg82m"] [ext_resource type="PackedScene" uid="uid://dgk88esxip5xi" path="res://items/knife.tscn" id="3_3gvdi"] -[ext_resource type="PackedScene" uid="uid://bxbocxdaayvwx" path="res://UI/progress_bar.tscn" id="6_racgh"] - -[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_3jbl6"] -properties/0/path = NodePath("Counter:position") -properties/0/spawn = false -properties/0/replication_mode = 1 -properties/1/path = NodePath("Counter:rotation") -properties/1/spawn = false -properties/1/replication_mode = 1 -properties/2/path = NodePath("Counter:process_result") -properties/2/spawn = false -properties/2/replication_mode = 1 -properties/3/path = NodePath("Counter:process_result_work") -properties/3/spawn = false -properties/3/replication_mode = 1 -properties/4/path = NodePath("Counter:work_progress") -properties/4/spawn = false -properties/4/replication_mode = 1 -properties/5/path = NodePath("Counter:visible") -properties/5/spawn = false -properties/5/replication_mode = 1 [sub_resource type="BoxShape3D" id="BoxShape3D_24d3s"] size = Vector3(0.48521727, 0.040039063, 0.41994628) @@ -46,20 +24,33 @@ albedo_color = Color(0.66595805, 0.53976387, 0.4331022, 1) [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vlqg6"] albedo_color = Color(1.1759251, 0.741115, 0.5692133, 1) -[node name="Counter" type="Node3D" unique_id=672880121] +[node name="Counter" unique_id=707500902 instance=ExtResource("1_station")] -[node name="StationMovement" parent="." unique_id=946873975 node_paths=PackedStringArray("station") instance=ExtResource("1_3jbl6")] +[node name="StationMovement" parent="." index="0" unique_id=946873975 node_paths=PackedStringArray("station")] station = NodePath("../Counter") -[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." unique_id=1583772931] -replication_config = SubResource("SceneReplicationConfig_3jbl6") +[node name="ProgressBar3D" parent="." index="4" unique_id=654673176] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2838624, -0.18) -[node name="Counter" type="StaticBody3D" parent="." unique_id=1487893288 node_paths=PackedStringArray("audio", "knife", "progress_bar") groups=["station"]] +[node name="SnapZone" parent="." index="5" unique_id=1315859105] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.0647464, 0) +collision_layer = 65536 +collision_mask = 65540 +stash_sound = ExtResource("2_0aadn") +snap_mode = 1 + +[node name="CollisionShape3D" parent="SnapZone" index="0"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.002, 0) +shape = SubResource("BoxShape3D_1ntq7") + +[node name="Counter" type="StaticBody3D" parent="." index="6" unique_id=1487893288 node_paths=PackedStringArray("audio", "knife", "snap_zone", "synchronizer", "progress_bar") groups=["station"]] script = ExtResource("1_oapbh") audio = NodePath("AudioStreamPlayer3D") chop_audio = ExtResource("2_lg82m") knife = NodePath("Knife") -progress_bar = NodePath("ProgressBar3D") +snap_zone = NodePath("../SnapZone") +synchronizer = NodePath("../MultiplayerSynchronizer") +progress_bar = NodePath("../ProgressBar3D") [node name="CollisionShape3DCuttingBoard" type="CollisionShape3D" parent="Counter" unique_id=706340473] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00088502467, 1.0178218, 0.0009101778) @@ -85,24 +76,6 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2838624, 0) freeze = true release_mode = 1 -[node name="XRToolsSnapZone" type="Area3D" parent="Counter" unique_id=1647380272 groups=["station_zone"]] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.0647464, 0) -collision_layer = 65536 -collision_mask = 65540 -script = ExtResource("1_dlkho") -stash_sound = ExtResource("2_0aadn") -snap_mode = 1 -metadata/_custom_type_script = "uid://cquqe4f1m1sw6" - -[node name="CollisionShape3D2" type="CollisionShape3D" parent="Counter/XRToolsSnapZone" unique_id=969340130] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.002, 0) -shape = SubResource("BoxShape3D_1ntq7") - -[node name="AudioStreamPlayer3D" type="AudioStreamPlayer3D" parent="Counter/XRToolsSnapZone" unique_id=1786831079] - -[node name="ProgressBar3D" parent="Counter" unique_id=654673176 instance=ExtResource("6_racgh")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2838624, -0.18) - [node name="CSGCombiner3D" type="CSGCombiner3D" parent="Counter" unique_id=451757283] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5038623, 0) @@ -155,5 +128,3 @@ operation = 2 size = Vector3(0.037109375, 0.092285156, 0.26757813) [connection signal="body_entered" from="Counter/GestureArea" to="Counter" method="_on_gesture_area_body_entered"] -[connection signal="has_dropped" from="Counter/XRToolsSnapZone" to="Counter" method="_on_snap_zone_dropped"] -[connection signal="has_picked_up" from="Counter/XRToolsSnapZone" to="Counter" method="_on_snap_zone_picked_up"] diff --git a/Stations/counter.gd b/Stations/counter.gd index 94191b9..354e5ef 100644 --- a/Stations/counter.gd +++ b/Stations/counter.gd @@ -1,4 +1,5 @@ -extends StaticBody3D +class_name Counter +extends WorkStation @export var chop_work_steps: float = 5.0 @export var chop_min_speed: float = 2.0 @@ -6,151 +7,97 @@ extends StaticBody3D @export var audio: AudioStreamPlayer3D @export var chop_audio: AudioStream @export var knife: XRToolsPickable -@onready var snap_zone: XRToolsSnapZone = $XRToolsSnapZone -@export var progress_bar: ProgressBar3D - -# Chopping state. Follow the hob/sink pattern so the display refreshes when -# values change; only the world owner runs the station's process in practice. -@export var process_result: String = "": set = _set_result -@export var process_result_work: float = 0.0: set = _set_result_work -@export var work_progress: float = 0.0: set = _set_work_progress func _ready() -> void: + super.ready() + SweetLogger.debug("Counter {0} _ready", [name]) if not audio: SweetLogger.warning("{0} missing audio reference", [name]) if not chop_audio: SweetLogger.warning("{0} missing chop_audio reference", [name]) - if not progress_bar or progress_bar is not ProgressBar3D: - SweetLogger.warning("{0} missing progress_bar reference", [name]) - if not knife or knife is not XRToolsPickable: + if not knife: SweetLogger.warning("{0} missing knife reference", [name]) - if not snap_zone or snap_zone is not XRToolsSnapZone: - SweetLogger.warning("{0} missing snap_zone reference", [name]) - - snap_zone.has_picked_up.connect(_on_object_picked_up) - snap_zone.has_dropped.connect(_on_object_dropped) - progress_bar.override_fill_color(Color.GREEN) - _hide_all_tools() - _refresh_progress_bar() - - -func _set_work_progress(value: float) -> void: - work_progress = value - _refresh_progress_bar() - - -func _set_result(value: String) -> void: - process_result = value - _refresh_progress_bar() - # When a chopping recipe is set, show the knife for the player to use. - if not process_result.is_empty(): - knife.visible = true - knife.enabled = true - SweetLogger.debug("Chopping recipe set: {0}", [process_result]) - else: - _hide_all_tools() - - -func _set_result_work(value: float) -> void: - process_result_work = value - _refresh_progress_bar() - - -func _refresh_progress_bar() -> void: - if not progress_bar: - return - var progress := 0.0 - if process_result != "" and process_result_work > 0: - progress = clampf(float(work_progress) / process_result_work, 0.0, 1.0) - - progress_bar.set_progress(progress) - progress_bar.set_bar_visible(not process_result.is_empty()) - progress_bar.override_fill_color(Color.GREEN) - - -# Add work from gesture area (knife hits). This increments the chopping progress. -func add_work(work: float) -> void: - SweetLogger.debug("Add work: {0}", [work]) - # Only the world owner should drive the authoritative state. Guarding is - # handled by higher-level NetworkManager logic elsewhere, mirror hob's - # convert_held_to_item which checks ownership before spawning. - work_progress += work - # Play chopping sound if available - if audio and chop_audio: - audio.stream = chop_audio - audio.play() - # If we've reached the required time, convert the held item - if process_result != "" and process_result_work > 0 and work_progress >= process_result_work: - SweetLogger.debug("Chopping complete, converting item to: {0}", [process_result]) - work_progress = 0 - convert_held_to_item(process_result) - - -func _on_gesture_area_body_entered(body: Node3D) -> void: - SweetLogger.debug("Gesture area entered: {0}", [body]) - if body.is_in_group("chopping_tool"): - if process_result == "": - SweetLogger.debug("Knife entered but nothing to chop") - return - - var speed := 0.0 - if body is RigidBody3D: - speed = body.linear_velocity.length() - elif body is CharacterBody3D: - speed = body.velocity.length() - - if speed < chop_min_speed: - SweetLogger.debug("Knife too slow for chopping: {0}", [speed]) - return - - add_work(chop_work_steps) - - -func _on_object_picked_up(_item: Variant) -> void: - SweetLogger.debug("Object picked up: {0}", [_item]) - var food_item = Helper.find_food_item(_item) - if not food_item: - SweetLogger.debug("Held object is not a FoodItem") - return - - var result = RecipeManager.get_chopping_result(food_item.id) - if not result: - SweetLogger.debug("Held a FoodItem that is not choppable, id: {0} process_result: {1}", [food_item.id, result]) - return - - process_result = result - process_result_work = RecipeManager.get_chopping_work(food_item.id) - SweetLogger.debug("Set process_result {0} work: {1}", [process_result, process_result_work]) - - -func _on_object_dropped(_item: Variant) -> void: - SweetLogger.debug("Object drop") - work_progress = 0 - process_result = "" - process_result_work = 0 _hide_all_tools() -func convert_held_to_item(_item: String) -> void: - if not NetworkManager.owns_world(): +func _start_chopping(id: String, work: float) -> void: + if not enabled: return - SweetLogger.debug("Converting {0}", [_item]) + result_id = id + max_work = work + SweetLogger.info("Start chopping - result_id: {0}, max_work: {1}", [result_id, max_work]) - var old_pickable = snap_zone.picked_up_object - if not old_pickable: - SweetLogger.warning("{0} finished processing item, but snap_zone is missing its reference", [name]) - return - var original_transform = old_pickable.global_transform - var new_scene_instance = NetworkManager.spawn_item(RecipeManager.get_item_scene(_item).resource_path, original_transform) +func _process(delta: float) -> void: + super.process(delta) - SweetLogger.debug("Freeing old_pickable {0}", [old_pickable]) - snap_zone.drop_object() - NetworkManager.despawn_item(old_pickable) - snap_zone.pick_up_object(new_scene_instance) func _hide_all_tools(): knife.visible = false knife.enabled = false + + + + +func _on_gesture_area_body_entered(body: Node3D) -> void: + SweetLogger.debug("Gesture area entered: {0}", [body]) + if not body.is_in_group("chopping_tool"): + return + if result_id == "": + SweetLogger.debug("Knife entered but nothing to chop") + return + + var speed := 0.0 + if body is RigidBody3D: + speed = body.linear_velocity.length() + elif body is CharacterBody3D: + speed = body.velocity.length() + + if speed < chop_min_speed: + SweetLogger.debug("Knife too slow for chopping: {0}", [speed]) + return + + if audio and chop_audio: + audio.stream = chop_audio + audio.play() + + add_work(chop_work_steps) + + +# Called from Station base class +func refresh_display() -> void: + super.refresh_display() + progress_bar.override_fill_color(Color.GREEN) + + +# Called from Station base class +func on_food_item_picked_up(food_item: FoodItem) -> void: + SweetLogger.debug("Object picked up: {0}", [food_item]) + + if not food_item: + SweetLogger.debug("Held object is not a FoodItem") + return + var result = RecipeManager.get_chopping_result(food_item.id) + if not result: + SweetLogger.debug("Held a FoodItem that is not choppable, id: {0} result: {1}", [food_item.id, result]) + return + + knife.visible = true + knife.enabled = true + _start_chopping(result, RecipeManager.get_chopping_work(food_item.id)) + + +# Called from Station base class +func on_object_dropped(_item: Node3D) -> void: + SweetLogger.debug("->[]") + _hide_all_tools() + reset() + + +# Called from Station base class +func on_work_complete(): + SweetLogger.debug("->[]") + _hide_all_tools() + convert_item() diff --git a/content/station_layouts/small_line.tscn b/content/station_layouts/small_line.tscn index 2a04b91..b086d4c 100644 --- a/content/station_layouts/small_line.tscn +++ b/content/station_layouts/small_line.tscn @@ -8,6 +8,7 @@ [ext_resource type="PackedScene" uid="uid://ck5tuftqmyiue" path="res://stations/plate_dispenser.tscn" id="6_b5gb1"] [ext_resource type="PackedScene" uid="uid://caf0xanmxbshy" path="res://stations/table.tscn" id="7_0342k"] [ext_resource type="PackedScene" uid="uid://cnjwtnhwh0i8q" path="res://stations/dirt_station.tscn" id="8_b5gb1"] +[ext_resource type="PackedScene" uid="uid://sc6i0i1f0o48" path="res://stations/potato_dispenser.tscn" id="9_ok0xr"] [node name="SmallLine" type="Node3D" unique_id=1844128818] @@ -33,3 +34,6 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.4, 0, 1.2) [node name="DirtStation" parent="." unique_id=784427347 instance=ExtResource("8_b5gb1")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.8000001, 0, 0) + +[node name="PotatoDispenser" parent="." unique_id=522124817 instance=ExtResource("9_ok0xr")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.8000001, 0, 0.6)