Refactor Counter

This commit is contained in:
JonShard
2026-08-14 13:45:46 +02:00
parent d7ccab2e3c
commit 8ecde66441
3 changed files with 100 additions and 178 deletions
+20 -49
View File
@@ -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"]
+50 -103
View File
@@ -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,91 +7,45 @@ 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:
func _start_chopping(id: String, work: float) -> void:
if not enabled:
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)
result_id = id
max_work = work
SweetLogger.info("Start chopping - result_id: {0}, max_work: {1}", [result_id, max_work])
func _process(delta: float) -> void:
super.process(delta)
func _hide_all_tools():
knife.visible = false
knife.enabled = false
# 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 == "":
if not body.is_in_group("chopping_tool"):
return
if result_id == "":
SweetLogger.debug("Knife entered but nothing to chop")
return
@@ -104,53 +59,45 @@ func _on_gesture_area_body_entered(body: Node3D) -> void:
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)
func _on_object_picked_up(_item: Variant) -> void:
SweetLogger.debug("Object picked up: {0}", [_item])
var food_item = Helper.find_food_item(_item)
# 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} process_result: {1}", [food_item.id, result])
SweetLogger.debug("Held a FoodItem that is not choppable, id: {0} 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])
knife.visible = true
knife.enabled = true
_start_chopping(result, RecipeManager.get_chopping_work(food_item.id))
func _on_object_dropped(_item: Variant) -> void:
SweetLogger.debug("Object drop")
work_progress = 0
process_result = ""
process_result_work = 0
# Called from Station base class
func on_object_dropped(_item: Node3D) -> void:
SweetLogger.debug("->[]")
_hide_all_tools()
reset()
func convert_held_to_item(_item: String) -> void:
if not NetworkManager.owns_world():
return
SweetLogger.debug("Converting {0}", [_item])
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)
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
# Called from Station base class
func on_work_complete():
SweetLogger.debug("->[]")
_hide_all_tools()
convert_item()
+4
View File
@@ -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)