7 Commits

Author SHA1 Message Date
JonShard e965cddde7 Fix Plates not disable/lock on clients in multiplayer 2026-08-21 15:46:01 +02:00
JonShard 5c4baa272a Fix Move windows script 2026-08-20 12:57:45 +02:00
JonShard 59bd3d1d66 Warning hunt 2026-08-20 12:22:07 +02:00
JonShard a79096eb1d Add check_reference helper 2026-08-20 11:46:00 +02:00
JonShard 6432dca31a Fix queue in multiplayer 2026-08-20 11:18:38 +02:00
JonShard 655751e5bd Change log levels and add more logging 2026-08-20 10:48:20 +02:00
JonShard 06dde91468 Fix plates not syncing dirty 2026-08-20 09:23:25 +02:00
39 changed files with 255 additions and 256 deletions
+2 -4
View File
@@ -23,10 +23,8 @@ var _pending_absorb: Array[Node3D] = []
func _ready() -> void: func _ready() -> void:
area_3d.body_entered.connect(_on_body_entered) area_3d.body_entered.connect(_on_body_entered)
if not area_3d: Helper.check_reference(self, area_3d, Area3D)
SweetLogger.warning("{0} missing area_3d reference", [name]) Helper.check_reference(self, xr_pickable, XRToolsPickable)
if not xr_pickable:
SweetLogger.warning("{0} missing xr_pickable reference", [name])
# Absorbing items is a server decision (the container's holder is server- # Absorbing items is a server decision (the container's holder is server-
+7 -1
View File
@@ -43,6 +43,9 @@ properties/3/replication_mode = 2
properties/4/path = NodePath("PlateController:is_dirty") properties/4/path = NodePath("PlateController:is_dirty")
properties/4/spawn = false properties/4/spawn = false
properties/4/replication_mode = 1 properties/4/replication_mode = 1
properties/5/path = NodePath("NetPickable:grabbable")
properties/5/spawn = false
properties/5/replication_mode = 1
[node name="Plate" type="RigidBody3D" unique_id=190487773] [node name="Plate" type="RigidBody3D" unique_id=190487773]
collision_layer = 4 collision_layer = 4
@@ -51,8 +54,11 @@ freeze_mode = 1
script = ExtResource("1_nq5sa") script = ExtResource("1_nq5sa")
second_hand_grab = 1 second_hand_grab = 1
[node name="PlateController" type="Node" parent="." unique_id=1503264193] [node name="PlateController" type="Node" parent="." unique_id=1503264193 node_paths=PackedStringArray("net_pickable", "dirty_node", "container")]
script = ExtResource("1_vjsmi") script = ExtResource("1_vjsmi")
net_pickable = NodePath("../NetPickable")
dirty_node = NodePath("../Dirty")
container = NodePath("../Container")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1365637864] [node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1365637864]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.007171631, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.007171631, 0)
+37 -15
View File
@@ -1,29 +1,51 @@
class_name PlateController class_name PlateController
extends Node extends Node
@onready var dirty_node: Node3D = $"../Dirty" @export var net_pickable: NetPickable
@onready var container: ItemContainer = $"../Container" @export var dirty_node: Node3D
@export var container: ItemContainer
@export var is_dirty: bool = false
## Synced summary of the plate's contents (item ids). The contents themselves ## Synced summary of the plate's contents (item ids). The contents themselves
## are the real item nodes ItemContainer reparents under the plate; this is only ## are the real item nodes ItemContainer reparents under the plate; this is only
## what other systems read to ask "what is on this plate" without walking them. ## what other systems read to ask "what is on this plate" without walking them.
@export var contained_ids: Array[String] = [] @export var contained_ids: Array[String] = []
@export var enabled = true:
get:
return enabled
set(value):
if NetworkManager.owns_world():
clients_set_enabled.rpc(value)
enabled = value
container.enabled = not is_dirty
net_pickable.grabbable = value
SweetLogger.info("Set plate enabled: {0}", [value])
@rpc("authority", "call_remote", "reliable")
func clients_set_enabled(value: bool) -> void:
enabled = value
@export var is_dirty: bool = false:
get:
return is_dirty
set(value):
if NetworkManager.owns_world():
clients_set_dirty.rpc(value)
is_dirty = value
container.enabled = not value
dirty_node.visible = value
SweetLogger.info("Set plate dirty: {0}", [value])
@rpc("authority", "call_remote", "reliable")
func clients_set_dirty(value: bool) -> void:
is_dirty = value
func get_food_items() -> Array[FoodItem]: func get_food_items() -> Array[FoodItem]:
return container.contained_items return container.contained_items
func _ready() -> void: func _ready() -> void:
if not dirty_node: Helper.check_reference(self, dirty_node, Node3D)
SweetLogger.warning("{0} missing dirty_node reference", [name]) Helper.check_reference(self, net_pickable, NetPickable)
dirty_node.visible = is_dirty Helper.check_reference(self, container, ItemContainer)
func _process(_delta: float) -> void:
if is_dirty:
container.enabled = false
dirty_node.visible = true
else:
container.enabled = true
dirty_node.visible = false
+2 -4
View File
@@ -33,13 +33,13 @@ var _original_freeze_mode: RigidBody3D.FreezeMode
# Same idea for the pickable's authored `enabled` flag, which the non-authority # Same idea for the pickable's authored `enabled` flag, which the non-authority
# branch of apply_held_state() clears while someone else is holding the item. # branch of apply_held_state() clears while someone else is holding the item.
var _original_enabled: bool @export var _original_enabled: bool
## Intent set by external game logic (e.g. a station enabling/disabling a tool), ## Intent set by external game logic (e.g. a station enabling/disabling a tool),
## independent of hold state. apply_held_state() is the sole writer of the ## independent of hold state. apply_held_state() is the sole writer of the
## pickable's actual `enabled` property, so this is how other systems express ## pickable's actual `enabled` property, so this is how other systems express
## "should be enabled" without fighting that reconciliation every tick. ## "should be enabled" without fighting that reconciliation every tick.
var grabbable: bool = true: set = set_grabbable @export var grabbable: bool = true: set = set_grabbable
func _ready() -> void: func _ready() -> void:
_pickable = get_parent() as XRToolsPickable _pickable = get_parent() as XRToolsPickable
@@ -179,8 +179,6 @@ func apply_held_state() -> void:
and _pickable.collision_mask == 0 \ and _pickable.collision_mask == 0 \
and _pickable.enabled == want_enabled: and _pickable.enabled == want_enabled:
return return
if NetworkManager.is_online(): # This was spamming that Knife was frozen every frame.
SweetLogger.debug("{0}: freezing (non-authority, owner=peer {1})", [_pickable.name, net_held_by])
_pickable.freeze = true _pickable.freeze = true
_pickable.freeze_mode = RigidBody3D.FREEZE_MODE_KINEMATIC _pickable.freeze_mode = RigidBody3D.FREEZE_MODE_KINEMATIC
_pickable.collision_mask = 0 _pickable.collision_mask = 0
+2
View File
@@ -431,6 +431,8 @@ func request_join(ip: String) -> void:
pending_ip = ip pending_ip = ip
func consume_pending_session() -> void: func consume_pending_session() -> void:
if is_online():
return
if pending_action == "host": if pending_action == "host":
pending_action = "" pending_action = ""
host() host()
+3 -5
View File
@@ -14,14 +14,11 @@ var _food_item: FoodItem
func _ready() -> void: func _ready() -> void:
SweetLogger.debug("{0} ready", [_pickable.name]) SweetLogger.debug("{0} ready", [_pickable.name])
_food_item = get_parent().get_node_or_null("FoodItem") as FoodItem _food_item = get_parent().get_node_or_null("FoodItem") as FoodItem
if not _food_item:
SweetLogger.warning("{0} missing FoodItem reference, must be a sibling of a FoodItem", [get_parent().name])
if not _pickable: if not _pickable:
SweetLogger.error("{0} must be a grandchild of an XRToolsPickable", [get_parent().name]) SweetLogger.error("{0} must be a grandchild of an XRToolsPickable", [get_parent().name])
return return
if not _food_item: if not Helper.check_reference(get_parent(), _food_item, FoodItem):
SweetLogger.warning("{0} requires a FoodItem sibling", [_pickable.name])
return return
if not enabled: if not enabled:
return return
@@ -73,11 +70,12 @@ func _on_body_entered(body: Node3D) -> void:
# Instantiate the result of combination and free the two ingredient items # Instantiate the result of combination and free the two ingredient items
func _combine(other_body: Node3D, result: PackedScene) -> void: func _combine(other_body: Node3D, result: PackedScene) -> void:
SweetLogger.debug("Combining {0} + {1} into {2}", [_food_item.id, Helper.find_food_item(other_body).id, result.resource_path]) SweetLogger.info("Combining {0} + {1} into {2}", [_food_item.id, Helper.find_food_item(other_body).id, result.resource_path])
# Get Snapzone # Get Snapzone
var snap_zone := _pickable.get_picked_up_by() var snap_zone := _pickable.get_picked_up_by()
if not snap_zone or not snap_zone.has_method("pick_up_object"): if not snap_zone or not snap_zone.has_method("pick_up_object"):
SweetLogger.warning("{0}: combine triggered but base item is not in a snap zone, aborting", [_pickable.name])
return return
# Spawn the result through the server (so it replicates to every peer, # Spawn the result through the server (so it replicates to every peer,
+1 -2
View File
@@ -5,5 +5,4 @@ extends Node
@export var turns_into: PackedScene @export var turns_into: PackedScene
func _ready() -> void: func _ready() -> void:
if not turns_into: Helper.check_reference(self, turns_into, PackedScene)
SweetLogger.warning("{0} missing turns_into reference", [name])
+1 -3
View File
@@ -5,9 +5,7 @@ extends Node3D
func _ready() -> void: func _ready() -> void:
Helper.check_reference(self, kitchen_scene, PackedScene)
if not kitchen_scene:
SweetLogger.warning("{0} missing kitchen_scene reference", [name])
SweetLogger.debug("->[]") SweetLogger.debug("->[]")
+3 -3
View File
@@ -29,10 +29,10 @@ size = Vector3(16, 0.1, 16)
background_mode = 2 background_mode = 2
sky = ExtResource("5_kh26v") sky = ExtResource("5_kh26v")
reflected_light_source = 2 reflected_light_source = 2
ssr_enabled = true ssr_enabled = false
ssao_enabled = true ssao_enabled = true
ssil_enabled = true ssil_enabled = false
sdfgi_enabled = true sdfgi_enabled = false
[sub_resource type="BoxShape3D" id="BoxShape3D_24d3s"] [sub_resource type="BoxShape3D" id="BoxShape3D_24d3s"]
size = Vector3(16, 10, 0.1) size = Vector3(16, 10, 0.1)
+3 -3
View File
@@ -30,10 +30,10 @@ ambient_light_source = 3
ambient_light_color = Color(1, 1, 1, 1) ambient_light_color = Color(1, 1, 1, 1)
ambient_light_sky_contribution = 0.9 ambient_light_sky_contribution = 0.9
reflected_light_source = 2 reflected_light_source = 2
ssr_enabled = true ssr_enabled = false
ssao_enabled = true ssao_enabled = true
ssil_enabled = true ssil_enabled = false
sdfgi_enabled = true sdfgi_enabled = false
[sub_resource type="BoxShape3D" id="BoxShape3D_vlqg6"] [sub_resource type="BoxShape3D" id="BoxShape3D_vlqg6"]
size = Vector3(20, 0.1, 20) size = Vector3(20, 0.1, 20)
+17 -6
View File
@@ -9,18 +9,24 @@ var customers_served: int = 0
func _ready() -> void: func _ready() -> void:
GameManager.set_game_state(GameManager.GameState.BUILDING) if NetworkManager.owns_world():
GameManager.set_game_state(GameManager.GameState.BUILDING)
Signals.game_state_changed.connect(_on_game_state_changed) Signals.game_state_changed.connect(_on_game_state_changed)
Signals.table_satisfied.connect(_on_table_statisfied)
func _on_game_state_changed(new_state: GameManager.GameState) -> void: func _on_game_state_changed(new_state: GameManager.GameState) -> void:
if new_state == GameManager.GameState.RUNNING: if new_state == GameManager.GameState.RUNNING:
start_next_day() start_next_day()
func _on_table_statisfied(_table: Table) -> void:
customers_served += 1
SweetLogger.info("Spawned: {0} served: {1}, per_day: {2} time_remaining: {3}, progress: {4}", [customers_spawned, customers_served, GameManager.customers_per_day, snappedf(day_time_remaining, 0.1), snappedf(get_day_progression(), 0.1)])
# Returns 0-1 progress of the day time # Returns 0-1 progress of the day time
func get_day_progression() -> float: func get_day_progression() -> float:
return 1 - (day_time_remaining / GameManager.day_length_seconds) return clampf(1 - (day_time_remaining / GameManager.day_length_seconds), 0.0, 1.0)
func _reset_values() -> void: func _reset_values() -> void:
@@ -39,18 +45,23 @@ func start_next_day() -> void:
func finish_current_day() -> void: func finish_current_day() -> void:
SweetLogger.info("Finishing current day") SweetLogger.info("Finishing current day")
_reset_values() _reset_values()
GameManager.set_game_state(GameManager.GameState.BUILDING)
func _process(delta: float) -> void: func _process(delta: float) -> void:
if not NetworkManager.owns_world():
return
if GameManager.game_state != GameManager.GameState.RUNNING: if GameManager.game_state != GameManager.GameState.RUNNING:
return return
day_time_remaining -= delta if day_time_remaining > 0:
day_time_remaining -= delta
day_time_remaining = max(0, day_time_remaining)
var customers_at_this_time = GameManager.customers_per_day * get_day_progression() var customers_at_this_time = GameManager.customers_per_day * get_day_progression()
#print("DayController: customers_at_this_time: ", customers_at_this_time)
if customers_spawned < customers_at_this_time: if customers_spawned < customers_at_this_time:
customers_spawned += 1 customers_spawned += 1
SweetLogger.debug("Spawning customer") SweetLogger.info("Requesting to spawn customer")
Signals.request_customer_spawn.emit() Signals.request_customer_spawn.emit()
# If day complete # If day complete
if GameManager.customers_per_day == customers_served and customers_spawned == GameManager.customers_per_day: if GameManager.customers_per_day == customers_served and customers_spawned == GameManager.customers_per_day:
+3 -3
View File
@@ -18,10 +18,10 @@ size = Vector3(15, 0.1, 15)
background_mode = 2 background_mode = 2
sky = ExtResource("5_l1qm6") sky = ExtResource("5_l1qm6")
reflected_light_source = 2 reflected_light_source = 2
ssr_enabled = true ssr_enabled = false
ssao_enabled = true ssao_enabled = true
ssil_enabled = true ssil_enabled = false
sdfgi_enabled = true sdfgi_enabled = false
[node name="Main" type="Node3D" unique_id=1312265607] [node name="Main" type="Node3D" unique_id=1312265607]
script = ExtResource("1_jfr2g") script = ExtResource("1_jfr2g")
+3 -3
View File
@@ -24,10 +24,10 @@ size = Vector3(15, 0.1, 15)
background_mode = 2 background_mode = 2
sky = ExtResource("5_c3xgf") sky = ExtResource("5_c3xgf")
reflected_light_source = 2 reflected_light_source = 2
ssr_enabled = true ssr_enabled = false
ssao_enabled = true ssao_enabled = true
ssil_enabled = true ssil_enabled = false
sdfgi_enabled = true sdfgi_enabled = false
[sub_resource type="BoxShape3D" id="BoxShape3D_arao0"] [sub_resource type="BoxShape3D" id="BoxShape3D_arao0"]
size = Vector3(15, 20, 0.1) size = Vector3(15, 20, 0.1)
+19 -11
View File
@@ -6,10 +6,10 @@ extends Node3D
@export var progress_bar_3d: ProgressBar3D @export var progress_bar_3d: ProgressBar3D
@export var label_3d: Label3D @export var label_3d: Label3D
var _customers: Array[float] = [] # Temp. Array of their patience var _customers: Array[float] = [] # Temp. Array of their patience
var _tables: Array[Node3D] = [] var _tables: Array[Node3D] = []
func _ready() -> void: func _ready() -> void:
progress_bar_3d.override_fill_color(Color.YELLOW) progress_bar_3d.override_fill_color(Color.YELLOW)
progress_bar_3d.exponential = true progress_bar_3d.exponential = true
@@ -21,6 +21,7 @@ func _on_game_state_changed(new_state: GameManager.GameState) -> void:
if new_state == GameManager.GameState.RUNNING: if new_state == GameManager.GameState.RUNNING:
_rebuild_table_list() _rebuild_table_list()
func _on_request_customer_spawn() -> void: func _on_request_customer_spawn() -> void:
spawn_customer() spawn_customer()
@@ -44,20 +45,27 @@ func _try_to_assign_customers() -> void:
break break
func _update_clients_display() -> void:
if not _customers.is_empty():
everyone_set_queue_info.rpc("Customers in queue: " + str(_customers.size()), _customers.front() / queue_patience)
else:
everyone_set_queue_info.rpc("No Customers", 0)
@rpc("authority", "call_local", "unreliable")
func everyone_set_queue_info(label_text: String, progress: float) -> void:
label_3d.text = label_text
progress_bar_3d.set_progress(progress)
func _process(delta: float) -> void: func _process(delta: float) -> void:
if not NetworkManager.owns_world():
return
# Process customers patience # Process customers patience
for i in range(0, _customers.size()): for i in range(0, _customers.size()):
_customers[i] -= delta _customers[i] -= delta
if _customers[i] <= 0: if _customers[i] <= 0:
SweetLogger.info("Customer patience ran out, game over")
GameManager.game_over() GameManager.game_over()
_try_to_assign_customers() _try_to_assign_customers()
_update_clients_display()
# Update visuals
if not _customers.is_empty():
label_3d.text = "Customers in queue: " + str(_customers.size())
progress_bar_3d.set_progress(_customers.front() / queue_patience)
else:
progress_bar_3d.set_progress(0)
label_3d.text = "No Customers"
+3 -3
View File
@@ -24,10 +24,10 @@ ambient_light_source = 3
ambient_light_color = Color(1, 1, 1, 1) ambient_light_color = Color(1, 1, 1, 1)
ambient_light_sky_contribution = 0.9 ambient_light_sky_contribution = 0.9
reflected_light_source = 2 reflected_light_source = 2
ssr_enabled = true ssr_enabled = false
ssao_enabled = true ssao_enabled = true
ssil_enabled = true ssil_enabled = false
sdfgi_enabled = true sdfgi_enabled = false
[sub_resource type="BoxShape3D" id="BoxShape3D_vlqg6"] [sub_resource type="BoxShape3D" id="BoxShape3D_vlqg6"]
size = Vector3(20, 0.1, 20) size = Vector3(20, 0.1, 20)
+3 -6
View File
@@ -12,12 +12,9 @@ extends WorkStation
func _ready() -> void: func _ready() -> void:
super.ready() super.ready()
SweetLogger.debug("Counter {0} _ready", [name]) SweetLogger.debug("Counter {0} _ready", [name])
if not audio: Helper.check_reference(self, audio, AudioStreamPlayer3D)
SweetLogger.warning("{0} missing audio reference", [name]) Helper.check_reference(self, chop_audio, AudioStream)
if not chop_audio: Helper.check_reference(self, knife, XRToolsPickable)
SweetLogger.warning("{0} missing chop_audio reference", [name])
if not knife:
SweetLogger.warning("{0} missing knife reference", [name])
_disable_all_tools() _disable_all_tools()
+1 -2
View File
@@ -9,8 +9,7 @@ extends WorkStation
func _ready() -> void: func _ready() -> void:
super.ready() super.ready()
SweetLogger.debug("Hob {0} _ready", [name]) SweetLogger.debug("Hob {0} _ready", [name])
if not animation_player: Helper.check_reference(self, animation_player, AnimationPlayer)
SweetLogger.warning("{0} missing animation_player reference", [name])
func _start_cooking(id: String, work: float) -> void: func _start_cooking(id: String, work: float) -> void:
animation_player.play("hob") animation_player.play("hob")
+1 -2
View File
@@ -7,8 +7,7 @@ extends Station
func _ready() -> void: func _ready() -> void:
super.ready() super.ready()
SweetLogger.debug("ItemDispenser {0} _ready", [name]) SweetLogger.debug("ItemDispenser {0} _ready", [name])
if not item_scene: Helper.check_reference(self, item_scene, PackedScene)
SweetLogger.warning("{0} missing item_scene reference", [name])
func _process(delta: float) -> void: func _process(delta: float) -> void:
+3 -6
View File
@@ -38,12 +38,9 @@ func _on_station_bought(_instance: Node3D):
func _ready() -> void: func _ready() -> void:
SweetLogger.debug("->[]") SweetLogger.debug("->[]")
if not station: Helper.check_reference(self, station, StaticBody3D)
SweetLogger.warning("{0} missing station reference", [name]) Helper.check_reference(self, move_handle, XRToolsPickable)
if not move_handle: Helper.check_reference(self, move_ghost, Area3D)
SweetLogger.warning("{0} missing move_handle reference", [name])
if not move_ghost:
SweetLogger.warning("{0} missing move_ghost reference", [name])
move_handle_rigid = move_handle as RigidBody3D move_handle_rigid = move_handle as RigidBody3D
original_collision_layer = station.collision_layer original_collision_layer = station.collision_layer
+21 -63
View File
@@ -8,13 +8,13 @@ extends SharedInventoryStation
@export var eating_duration: float = 5.0 @export var eating_duration: float = 5.0
@export var money_sound: AudioStream @export var money_sound: AudioStream
@onready var label_3d: Label3D = $Label3D @export var label_3d: Label3D
@onready var label_3d_time: Label3D = $Label3DTime @export var label_3d_time: Label3D
@onready var snap_zones: Array[XRToolsSnapZone] = [] @export var snap_zones: Array[XRToolsSnapZone]
@onready var progress_bar: ProgressBar3D = $ProgressBar3D @export var progress_bar: ProgressBar3D
@onready var audio_player: AudioStreamPlayer3D = $AudioStreamPlayer3D @export var audio_player: AudioStreamPlayer3D
@onready var customers: Node3D = $Customers @export var customers: Node3D
@onready var player_detect_area_3d: Area3D = $PlayerDetectArea3D @export var player_detect_area_3d: Area3D
const lbl_thinking: String = "..." const lbl_thinking: String = "..."
const lbl_ordering: String = "!" const lbl_ordering: String = "!"
@@ -66,16 +66,6 @@ func server_place_order() -> void:
place_order() place_order()
func absorb_items():
SweetLogger.debug("->[]")
for snap_zone_node in snap_zones:
var held_object = snap_zone_node.picked_up_object
if not held_object:
continue
_absorb_item_if_correct(held_object)
# Flattens items held across all of this table's snap zones # Flattens items held across all of this table's snap zones
func get_exposed_food_items() -> Array[FoodItem]: func get_exposed_food_items() -> Array[FoodItem]:
var items: Array[FoodItem] = [] var items: Array[FoodItem] = []
@@ -83,7 +73,7 @@ func get_exposed_food_items() -> Array[FoodItem]:
var held_object = zone.picked_up_object var held_object = zone.picked_up_object
if not held_object: if not held_object:
continue continue
var plate: PlateController = _get_plate_controller_from_item(held_object) var plate: PlateController = Helper.find_first_child_of_type(held_object, PlateController)
if plate: if plate:
items.append_array(plate.container.contained_items) items.append_array(plate.container.contained_items)
continue continue
@@ -119,10 +109,11 @@ func clearAllFood() -> void:
if not held_object: if not held_object:
continue continue
var plate: PlateController = _get_plate_controller_from_item(held_object) var plate: PlateController = Helper.find_first_child_of_type(held_object, PlateController)
var food_item: FoodItem = Helper.find_food_item(held_object) var food_item: FoodItem = Helper.find_food_item(held_object)
if plate: if plate:
plate.container.clear() plate.container.clear()
plate.enabled = true
plate.is_dirty = true plate.is_dirty = true
# Side or other food item directly on table # Side or other food item directly on table
@@ -147,24 +138,17 @@ func _enter_tree() -> void:
sync_config.add_property(property_path) sync_config.add_property(property_path)
sync_config.property_set_spawn(property_path, false) sync_config.property_set_spawn(property_path, false)
sync_config.property_set_replication_mode(property_path, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE) sync_config.property_set_replication_mode(property_path, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE)
SweetLogger.info("DEBUG sync_config properties: {0} | root_path: {1} | authority: {2} | peer: {3}", [sync_config.get_properties(), synchronizer.root_path, get_multiplayer_authority(), multiplayer.get_unique_id()]) # temp diagnostic SweetLogger.debug("sync_config properties: {0} | root_path: {1} | authority: {2} | peer: {3}", [sync_config.get_properties(), synchronizer.root_path, get_multiplayer_authority(), multiplayer.get_unique_id()])
func _ready() -> void: func _ready() -> void:
super.ready() super.ready()
if not label_3d: Helper.check_reference(self, label_3d, Label3D)
SweetLogger.warning("{0} missing label_3d reference", [name]) Helper.check_reference(self, label_3d_time, Label3D)
if not label_3d_time: Helper.check_reference(self, progress_bar, ProgressBar3D)
SweetLogger.warning("{0} missing label_3d_time reference", [name])
if not progress_bar or progress_bar is not ProgressBar3D:
SweetLogger.warning("{0} missing progress_bar reference", [name])
progress_bar.y_billboard = true progress_bar.y_billboard = true
progress_bar.exponential = true progress_bar.exponential = true
# Render whatever state already arrived from the server before we were in Helper.check_reference(self, audio_player, AudioStreamPlayer3D)
# the tree (see the guard in _refresh_display).
_refresh_display.call_deferred()
if not audio_player:
SweetLogger.warning("{0} missing audio_player reference", [name])
# Get snap_zones for plates, store in array snap_zones # Get snap_zones for plates, store in array snap_zones
for child in get_children(): for child in get_children():
@@ -200,10 +184,6 @@ func _on_object_dropped(_item) -> void:
_unsatisfied_orders.append(food_item.id) _unsatisfied_orders.append(food_item.id)
# original : burger cube, cube
# unsatisfied : burger cube
# table :
# There is no on_stay signal, we have to track player with bool # There is no on_stay signal, we have to track player with bool
func _on_player_enter(_body): func _on_player_enter(_body):
_players_count += 1 _players_count += 1
@@ -217,20 +197,6 @@ func _on_player_exit(_body):
SweetLogger.debug("Player exit, players_count: {0}", [_players_count]) SweetLogger.debug("Player exit, players_count: {0}", [_players_count])
func _get_plate_controller_from_item(_item: Node) -> PlateController:
if not _item:
SweetLogger.debug("Item is null")
return null
for child in _item.get_children():
if child is PlateController:
SweetLogger.debug("Found child")
return child
SweetLogger.debug("No match")
return null
func _absorb_item_if_correct(_item: Node) -> void: func _absorb_item_if_correct(_item: Node) -> void:
SweetLogger.debug("Absorb item if correct, item: {0}", [_item]) SweetLogger.debug("Absorb item if correct, item: {0}", [_item])
if not _item: if not _item:
@@ -239,16 +205,15 @@ func _absorb_item_if_correct(_item: Node) -> void:
return return
# Plate: Get plate controller in child of _item (hopefully a plate XRpickable) # Plate: Get plate controller in child of _item (hopefully a plate XRpickable)
var plate_controller = _get_plate_controller_from_item(_item) var plate_controller: PlateController = Helper.find_first_child_of_type(_item, PlateController)
SweetLogger.debug("Plate_controller ref: {0}", [plate_controller]) SweetLogger.debug("Plate_controller ref: {0}", [plate_controller])
_item.print_tree_pretty()
if plate_controller: if plate_controller:
# Absorm items from the plate we want # Absorm items from the plate we want
for food_item: FoodItem in plate_controller.container.contained_items: # TOOD: handle registering the meal again when a side is added to the plate for food_item: FoodItem in plate_controller.container.contained_items: # TOOD: handle registering the meal again when a side is added to the plate
if food_item.id in _unsatisfied_orders and not food_item.is_absorbed: if food_item.id in _unsatisfied_orders and not food_item.is_absorbed:
SweetLogger.debug("Held a plate with FoodItem that is in unsatisfied orders, removing it") SweetLogger.debug("Held a plate with FoodItem that is in unsatisfied orders, removing it")
(plate_controller.get_parent() as XRToolsPickable).get_picked_up_by().enabled = false # Lock meal that is deliverd plate_controller.enabled = false # Lock plate
_unsatisfied_orders.erase(food_item.id) _unsatisfied_orders.erase(food_item.id)
food_item.is_absorbed = true food_item.is_absorbed = true
_update_state_from_orders() _update_state_from_orders()
@@ -282,7 +247,7 @@ func _collect_money_from_food():
if not held_object: if not held_object:
continue continue
var plate: PlateController = _get_plate_controller_from_item(held_object) var plate: PlateController = Helper.find_first_child_of_type(held_object, PlateController)
var food_item: FoodItem = Helper.find_food_item(held_object) var food_item: FoodItem = Helper.find_food_item(held_object)
if plate: if plate:
for fi: FoodItem in plate.get_food_items(): for fi: FoodItem in plate.get_food_items():
@@ -359,23 +324,16 @@ func _state_end(oldState: TableState):
clearAllFood() clearAllFood()
_set_snap_zones_enabled(true) _set_snap_zones_enabled(true)
_set_state(TableState.EMPTY) _set_state(TableState.EMPTY)
SweetLogger.info("Table satisfied, emitting signal")
Signals.table_satisfied.emit(self)
TableState.ORDERING, TableState.WAITING_PRIMARY, TableState.WAITING_FRIEND: TableState.ORDERING, TableState.WAITING_PRIMARY, TableState.WAITING_FRIEND:
SweetLogger.info("{0}: order timed out in state {1}, game over", [name, TableState.keys()[oldState]])
label_3d.text = lbl_gameover label_3d.text = lbl_gameover
GameManager.game_over() GameManager.game_over()
## Pure presentation, driven off the current (locally authoritative or
## synced-from-server) state. Runs on every peer.
func _refresh_display() -> void: func _refresh_display() -> void:
# _state, _state_time and _unsatisfied_orders are replicated with spawn=true,
# and MultiplayerSpawner applies a spawn payload BEFORE the node enters the
# tree — so these setters fire while the @onready children below are still
# null. Bail out until _ready() has resolved them; _ready() calls back in
# once it has, so nothing that arrived early is lost.
if not progress_bar or not label_3d or not label_3d_time:
SweetLogger.warning("{0} missing progress_bar or label reference", [name])
return
match _state: match _state:
TableState.IDLE: TableState.IDLE:
progress_bar.set_bar_visible(false) progress_bar.set_bar_visible(false)
+8 -1
View File
@@ -33,9 +33,16 @@ visible = false
[node name="SnapZone" parent="." index="5" unique_id=1315859105] [node name="SnapZone" parent="." index="5" unique_id=1315859105]
enabled = false enabled = false
[node name="Table" type="StaticBody3D" parent="." index="6" unique_id=1863572470 node_paths=PackedStringArray("notification_audio", "ambient_audio", "snap_zone", "synchronizer") groups=["station", "table"]] [node name="Table" type="StaticBody3D" parent="." index="6" unique_id=1863572470 node_paths=PackedStringArray("label_3d", "label_3d_time", "snap_zones", "progress_bar", "audio_player", "customers", "player_detect_area_3d", "notification_audio", "ambient_audio", "snap_zone", "synchronizer") groups=["station", "table"]]
script = ExtResource("1_2vcpj") script = ExtResource("1_2vcpj")
money_sound = ExtResource("2_jslhm") money_sound = ExtResource("2_jslhm")
label_3d = NodePath("Label3D")
label_3d_time = NodePath("Label3DTime")
snap_zones = [NodePath("XRToolsSnapZone")]
progress_bar = NodePath("ProgressBar3D")
audio_player = NodePath("AudioStreamPlayer3D")
customers = NodePath("Customers")
player_detect_area_3d = NodePath("PlayerDetectArea3D")
probe_paths = Array[NodePath]([NodePath("ProbeForward"), NodePath("ProbeRight"), NodePath("ProbeBack"), NodePath("ProbeLeft")]) probe_paths = Array[NodePath]([NodePath("ProbeForward"), NodePath("ProbeRight"), NodePath("ProbeBack"), NodePath("ProbeLeft")])
pickup_sound = ExtResource("3_0s6ir") pickup_sound = ExtResource("3_0s6ir")
drop_sound = ExtResource("3_0s6ir") drop_sound = ExtResource("3_0s6ir")
+3 -2
View File
@@ -9,8 +9,9 @@ class_name ProgressBar3D
func _ready() -> void: func _ready() -> void:
if not progress_bar: Helper.check_reference(self, progress_bar, ProgressBar)
SweetLogger.warning("{0} missing progress_bar reference", [name]) # Rebind now that SubViewport is guaranteed live, avoiding a stale ViewportTexture.
sprite_3d.texture = sprite_3d.get_node(^"SubViewport").get_texture()
if y_billboard: if y_billboard:
$Sprite3D.billboard = BaseMaterial3D.BillboardMode.BILLBOARD_FIXED_Y $Sprite3D.billboard = BaseMaterial3D.BillboardMode.BILLBOARD_FIXED_Y
+1 -1
View File
@@ -21,7 +21,7 @@ func _process(_delta: float) -> void:
func _on_button_pressed() -> void: func _on_button_pressed() -> void:
SweetLogger.debug("Buy {0}", [station_name]) SweetLogger.info("Buy {0}", [station_name])
_buy_station() _buy_station()
+7 -11
View File
@@ -20,7 +20,7 @@ var sync_config: SceneReplicationConfig
var enabled: bool: # When disabled the station only updated display and sounds. var enabled: bool: # When disabled the station only updated display and sounds.
get: return snap_zone.enabled get: return snap_zone.enabled
set(p_enabled): set(p_enabled):
SweetLogger.info("Set enabled {0} on station {1} on client {2}", [p_enabled, name, multiplayer.get_unique_id()]) SweetLogger.debug("Set enabled {0} on station {1} on client {2}", [p_enabled, name, multiplayer.get_unique_id()])
snap_zone.enabled = p_enabled snap_zone.enabled = p_enabled
snap_zone.set_process(p_enabled) snap_zone.set_process(p_enabled)
@@ -39,14 +39,10 @@ func _enter_tree() -> void:
# The child station has to call super.ready() for this to be called # The child station has to call super.ready() for this to be called
func ready() -> void: func ready() -> void:
SweetLogger.debug("Station {0} ready", [name]) SweetLogger.debug("Station {0} ready", [name])
if not notification_audio: Helper.check_reference(self, notification_audio, AudioStreamPlayer3D)
SweetLogger.warning("{0} missing notification_audio reference", [name]) Helper.check_reference(self, ambient_audio, AudioStreamPlayer3D)
if not ambient_audio: Helper.check_reference(self, snap_zone, XRToolsSnapZone)
SweetLogger.warning("{0} missing ambient_audio reference", [name]) Helper.check_reference(self, synchronizer, MultiplayerSynchronizer)
if not snap_zone:
SweetLogger.warning("{0} missing snap_zone reference", [name])
if not synchronizer:
SweetLogger.warning("{0} missing synchronizer reference", [name])
# Disable if we're not the server. # Disable if we're not the server.
if not NetworkManager.owns_world(): if not NetworkManager.owns_world():
enabled = false enabled = false
@@ -75,7 +71,7 @@ func _on_object_dropped_handler(item: Node3D) -> void:
func _apply_object_picked_up(item: Node3D) -> void: func _apply_object_picked_up(item: Node3D) -> void:
SweetLogger.debug("Pickup: {0}", [item.name]) SweetLogger.info("{0}: Pickup: {1}", [name, item.name])
Helper.play_sound(notification_audio, pickup_sound) Helper.play_sound(notification_audio, pickup_sound)
on_object_picked_up(item) on_object_picked_up(item)
var food_item = Helper.find_food_item(item) var food_item = Helper.find_food_item(item)
@@ -85,7 +81,7 @@ func _apply_object_picked_up(item: Node3D) -> void:
func _apply_object_dropped(item: Node3D) -> void: func _apply_object_dropped(item: Node3D) -> void:
Helper.play_sound(notification_audio, drop_sound, 0.8) Helper.play_sound(notification_audio, drop_sound, 0.8)
SweetLogger.debug("Drop: {0}", [item.name]) SweetLogger.info("{0}: Drop: {1}", [name, item.name])
on_object_dropped(item) on_object_dropped(item)
var food_item = Helper.find_food_item(item) var food_item = Helper.find_food_item(item)
if food_item: if food_item:
+1 -2
View File
@@ -32,8 +32,7 @@ func _enter_tree() -> void:
# The child station has to call super.ready() for this to be called # The child station has to call super.ready() for this to be called
func ready() -> void: func ready() -> void:
super.ready() super.ready()
if not progress_bar: Helper.check_reference(self, progress_bar, ProgressBar3D)
SweetLogger.warning("{0} missing progress_bar reference", [name])
# The child station has to call super.process(delta) for this to be called # The child station has to call super.process(delta) for this to be called
@@ -1,4 +1,4 @@
[gd_scene load_steps=7 format=3 uid="uid://clujaf3u776a3"] [gd_scene load_steps=5 format=3 uid="uid://clujaf3u776a3"]
[ext_resource type="Script" uid="uid://eavk7267igp7" path="res://addons/godot-xr-tools/objects/viewport_2d_in_3d.gd" id="1"] [ext_resource type="Script" uid="uid://eavk7267igp7" path="res://addons/godot-xr-tools/objects/viewport_2d_in_3d.gd" id="1"]
[ext_resource type="Script" uid="uid://cpl5yiyf1ypft" path="res://addons/godot-xr-tools/objects/viewport_2d_in_3d_body.gd" id="2"] [ext_resource type="Script" uid="uid://cpl5yiyf1ypft" path="res://addons/godot-xr-tools/objects/viewport_2d_in_3d_body.gd" id="2"]
@@ -7,14 +7,6 @@
resource_local_to_scene = true resource_local_to_scene = true
size = Vector2(3, 2) size = Vector2(3, 2)
[sub_resource type="ViewportTexture" id="ViewportTexture_ufe4n"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_fvml0"]
transparency = 1
cull_mode = 2
albedo_texture = SubResource("ViewportTexture_ufe4n")
texture_filter = 1
[sub_resource type="BoxShape3D" id="4"] [sub_resource type="BoxShape3D" id="4"]
resource_local_to_scene = true resource_local_to_scene = true
size = Vector3(3, 2, 0.02) size = Vector3(3, 2, 0.02)
@@ -34,7 +26,6 @@ render_target_update_mode = 1
[node name="Screen" type="MeshInstance3D" parent="."] [node name="Screen" type="MeshInstance3D" parent="."]
mesh = SubResource("1") mesh = SubResource("1")
surface_material_override/0 = SubResource("StandardMaterial3D_fvml0")
[node name="StaticBody3D" type="StaticBody3D" parent="."] [node name="StaticBody3D" type="StaticBody3D" parent="."]
collision_layer = 5242881 collision_layer = 5242881
+2 -2
View File
@@ -1,6 +1,6 @@
extends Node extends Node
const enable_debug = true const enable_debug = false
var frame_count = 0 var frame_count = 0
# Inside SweetLogger or a static helper class: # Inside SweetLogger or a static helper class:
static func get_current_function_name() -> String: static func get_current_function_name() -> String:
@@ -98,7 +98,7 @@ const TIMESTAMP_BG_COLOR = "#1e3a5f"
#===================================================================================# #===================================================================================#
## Column widths for alignment (in characters) ## Column widths for alignment (in characters)
const PEER_ID_COLUMN_WIDTH = 6 const PEER_ID_COLUMN_WIDTH = 6
const LOG_TYPE_COLUMN_WIDTH = 12 const LOG_TYPE_COLUMN_WIDTH = 13
## Default mm:ss:ms; with SHOW_TIMESTAMP_HOURS, hh:mm:ss:ms ## Default mm:ss:ms; with SHOW_TIMESTAMP_HOURS, hh:mm:ss:ms
const TIMESTAMP_COLUMN_WIDTH_MMSSMS = 9 const TIMESTAMP_COLUMN_WIDTH_MMSSMS = 9
const TIMESTAMP_COLUMN_WIDTH_HHMMSSMS = 12 const TIMESTAMP_COLUMN_WIDTH_HHMMSSMS = 12
Binary file not shown.
+13 -35
View File
@@ -1,4 +1,4 @@
### Full game systems (hardest part) ### Scope - Full game systems (hardest part)
- Star day modifiers - Star day modifiers
- research unlock - research unlock
- Mess and cleaning (How it works in VR?) - Mess and cleaning (How it works in VR?)
@@ -20,24 +20,17 @@
- Fullbody tracking (Height calibration) - Fullbody tracking (Height calibration)
### Station inheritence suggestion ### Todo
Station - Complete SharedInventory
WorkStation (performs work on a food item to convert it) - Investigate Table::_absorb_item_if_correct # TOOD: handle registering the meal again when a side is added to the plate
Hob
Sink
Counter
StorageStation (one snap zone and list of positions, FILO item dispenser, like a gun magazine)
Shelf
PlateRak
Dishwasher
SharedInventoryStation (one snap zone, shares a list of connected stations with which items exist in each of them)
Table
Belt
Dispenser
### Bugs
- Plate not locked on clinets by table
- Rare times, plate not cleared / has buger on it after table eaten. New customer didn't accept it, so must have been empty, but server and client visuals had burger on plate.
- Table does not accept clinet that was already in player detect zone
- A hamburger in a station in build mode stays but becomes kinematic when entering build mode again, from build mode.
### Multiplayer bugs ### Multiplayer bugs
- despan flicker for clien broken
- client keep autorityu of thrown object until lands - client keep autorityu of thrown object until lands
- in build mode, snap zones off, stations disabled - in build mode, snap zones off, stations disabled
- players can steal from each others hands - players can steal from each others hands
@@ -59,7 +52,7 @@ extre rolling pin
mop mop
bin bin
## Food dispensers ### Food dispensers
burger burger
buns buns
potato potato
@@ -70,7 +63,7 @@ pasta plates
meat meat
cheese cheese
## Automation ### Automation
belt belt
inserter inserter
splitter splitter
@@ -79,12 +72,12 @@ blender
dishwasher dishwasher
flinger / catapult flinger / catapult
## Storage ### Storage
shelf shelf
freezer freezer
frozen prep station equivilant frozen prep station equivilant
## Control ### Control
Phone Phone
Napkins (no mess consumable) Napkins (no mess consumable)
sharp cutlery (eat faster consumable) sharp cutlery (eat faster consumable)
@@ -117,14 +110,10 @@ Shared INventory
- On new table available, QueueController tells front customer in queue to sit at table - On new table available, QueueController tells front customer in queue to sit at table
## Modifiers ## Modifiers
- Disposable plates. no washing. much less money - Disposable plates. no washing. much less money
## Weird ideas ## Weird ideas
- carry 4 plates. A snapzone on forearm that only accept plate, and drops it if tilted too much. Real waiter feel. - carry 4 plates. A snapzone on forearm that only accept plate, and drops it if tilted too much. Real waiter feel.
@@ -132,14 +121,3 @@ Shared INventory
## Research ## Research
- Reasearch is its own currency. - Reasearch is its own currency.
- You unlock items in shop with reseach points. Then you can buy them. You "buy" the same tile twice. - You unlock items in shop with reseach points. Then you can buy them. You "buy" the same tile twice.
## NEtwork TOTO
- Make gamemanager a node with syncroniser
- All stations need syncronizers
- Pickable not synced cooked burger on hob example
- Client purchases don't spawn items from shop. RPC adventure
- Client can not move stations including hobs, on_move handle drop is called, network pickable authority is given. but station not moved
+19
View File
@@ -19,3 +19,22 @@ Add (what) to singal dropped in snap_zone
picked_up_object.let_go(self, Vector3.ZERO, Vector3.ZERO) picked_up_object.let_go(self, Vector3.ZERO, Vector3.ZERO)
picked_up_object = null picked_up_object = null
highlight_updated.emit(self, enabled) highlight_updated.emit(self, enabled)
viewport_2d_in_3d.tscn:
Removed the baked ViewportTexture sub-resource (no viewport_path set, genuinely
invalid) that was the default material on the Screen mesh. The script always
builds and swaps in its own material at _ready(), so the baked one only
existed to be briefly invalid before being discarded, printing a spurious
"Viewport Texture must be set to use it" error on every instance (MainMenuPanel3D
at boot, the player's shop_menu_3d on avatar spawn).
Removed:
[sub_resource type="ViewportTexture" id="ViewportTexture_ufe4n"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_fvml0"]
transparency = 1
cull_mode = 2
albedo_texture = SubResource("ViewportTexture_ufe4n")
texture_filter = 1
And the reference to it on the Screen node:
surface_material_override/0 = SubResource("StandardMaterial3D_fvml0")
+2 -2
View File
@@ -21,7 +21,7 @@ func server_set_money(value: int) -> void: set_money(value)
func client_sync_money(value: int) -> void: money = value func client_sync_money(value: int) -> void: money = value
var day_number: int = 1: var day_number: int = 0:
get: get:
return day_number return day_number
@@ -110,7 +110,7 @@ func client_sync_day_length_seconds(value: float) -> void:
day_length_seconds = value day_length_seconds = value
var customers_per_day: float = 5.0: var customers_per_day: float = 3.0:
get: get:
return customers_per_day return customers_per_day
+20 -14
View File
@@ -20,22 +20,28 @@ static func load_recipes() -> void:
return return
var yaml_available := ClassDB.class_exists("YAML") var yaml_available := ClassDB.class_exists("YAML")
if yaml_available: if not yaml_available:
var result = ClassDB.class_call_static("YAML", "load_file", recipe_path) SweetLogger.error("YAML addon is not available, recipes.yaml can not be loaded")
if result != null and not result.has_error(): return
var data = result.get_data()
if typeof(data) != TYPE_DICTIONARY:
SweetLogger.warning("YAML addon parsed recipes.yaml but returned an unsupported structure")
_recipes = data var result = ClassDB.class_call_static("YAML", "load_file", recipe_path)
_build_scene_paths() if result == null or result.has_error():
_build_combining_map() SweetLogger.error("Failed to parse recipes.yaml: {0}", [result.get_error_message() if result else "null result"])
_build_cooking_map() return
_build_chopping_map()
_build_rolling_map()
_build_augmenting_map()
_loaded = true
var data = result.get_data()
if typeof(data) != TYPE_DICTIONARY:
SweetLogger.warning("YAML addon parsed recipes.yaml but returned an unsupported structure")
_recipes = data
_build_scene_paths()
_build_combining_map()
_build_cooking_map()
_build_chopping_map()
_build_rolling_map()
_build_augmenting_map()
_loaded = true
#print_all_recipes()
static func get_combination_result(first_id: StringName, second_id: StringName) -> PackedScene: static func get_combination_result(first_id: StringName, second_id: StringName) -> PackedScene:
load_recipes() load_recipes()
+6 -11
View File
@@ -1,12 +1,7 @@
extends Node extends Node
@warning_ignore("unused_signal") signal game_over
@warning_ignore("unused_signal") @warning_ignore("unused_signal") signal restart_game
signal game_over @warning_ignore("unused_signal") signal game_state_changed(new_state: GameManager.GameState)
@warning_ignore("unused_signal") @warning_ignore("unused_signal") signal station_bought(instance: Node3D)
signal restart_game @warning_ignore("unused_signal") signal request_customer_spawn()
@warning_ignore("unused_signal") @warning_ignore("unused_signal") signal table_satisfied(table: Table)
signal game_state_changed(new_state: GameManager.GameState)
@warning_ignore("unused_signal")
signal station_bought(instance: Node3D)
@warning_ignore("unused_signal")
signal request_customer_spawn()
+9 -9
View File
@@ -1,20 +1,20 @@
extends Node extends Node
## Nudge down from the screen top so the window's title bar/menu stays visible.
const SERVER_Y_OFFSET := 45
func _ready() -> void: func _ready() -> void:
if OS.has_feature("editor"): # Only the (non-VR) server window needs positioning; the VR instance's
# Force subwindows to be native OS windows instead of embedded viewports # window is left wherever the OS/editor puts it.
if OS.has_feature("editor") and OS.get_cmdline_args().has("--server"):
get_tree().root.gui_embed_subwindows = false get_tree().root.gui_embed_subwindows = false
get_tree().create_timer(0.05).timeout.connect(_position_window) get_tree().create_timer(0.05).timeout.connect(_position_window)
func _position_window() -> void: func _position_window() -> void:
var is_server: bool = OS.get_cmdline_args().has("--server")
var screen_rect: Rect2i = DisplayServer.screen_get_usable_rect(DisplayServer.window_get_current_screen()) var screen_rect: Rect2i = DisplayServer.screen_get_usable_rect(DisplayServer.window_get_current_screen())
@warning_ignore("integer_division") @warning_ignore("integer_division")
var window_width: int = screen_rect.size.x / 2 var window_width: int = screen_rect.size.x / 2
var window_height: int = int(screen_rect.size.y * (2.0 / 3.0)) var x_pos: int = screen_rect.position.x + window_width
var y_pos: int = screen_rect.position.y + SERVER_Y_OFFSET
DisplayServer.window_set_size(Vector2i(window_width - 10, window_height)) DisplayServer.window_set_position(Vector2i(x_pos, y_pos))
if is_server:
var x_pos: int = screen_rect.position.x + window_width
DisplayServer.window_set_position(Vector2i(x_pos, screen_rect.position.y))
+2
View File
@@ -15,10 +15,12 @@ func _unhandled_input(event: InputEvent) -> void:
# Kill all clients # Kill all clients
@rpc("any_peer", "call_local", "reliable") @rpc("any_peer", "call_local", "reliable")
func all_quit_game(): func all_quit_game():
SweetLogger.info("Quit game requested, killing all clients")
get_tree().quit() get_tree().quit()
# Finds any node of class/type Table and calls satisfyAllOrders() # Finds any node of class/type Table and calls satisfyAllOrders()
func satisfy_table_orders() -> void: func satisfy_table_orders() -> void:
SweetLogger.info("Debug: satisfying all table orders")
# Searches all nodes in the current running scene matching the class "Table" # Searches all nodes in the current running scene matching the class "Table"
var table_nodes = get_tree().root.find_children("*", "Table", true, false) var table_nodes = get_tree().root.find_children("*", "Table", true, false)
+16
View File
@@ -72,6 +72,22 @@ static func get_node_from_path(from: Node, node_path: NodePath) -> Node3D:
static func check_reference(node: Node, ref: Variant, type: Variant) -> bool:
if is_instance_valid(ref) and is_instance_of(ref, type):
return true
var type_name: String
if type is Script:
type_name = type.get_global_name()
else:
var probe: Object = type.new()
type_name = probe.get_class()
if not (probe is RefCounted):
probe.free()
SweetLogger.warning("{0} missing reference {1} ({2})", [node.name, type_name, _get_caller_label()])
return false
static func play_sound(player: AudioStreamPlayer3D, stream: AudioStream, pitch_scale: float = 1): static func play_sound(player: AudioStreamPlayer3D, stream: AudioStream, pitch_scale: float = 1):
if not player: if not player:
SweetLogger.warning("{0}: AudioStreamPlayer3D is null, can not play sound", [_get_caller_label()]) SweetLogger.warning("{0}: AudioStreamPlayer3D is null, can not play sound", [_get_caller_label()])
-1
View File
@@ -1 +0,0 @@
uid://be8o8m6xpp3kc
+3 -3
View File
@@ -24,10 +24,10 @@ size = Vector3(15, 0.1, 15)
background_mode = 2 background_mode = 2
sky = ExtResource("4_081u3") sky = ExtResource("4_081u3")
reflected_light_source = 2 reflected_light_source = 2
ssr_enabled = true ssr_enabled = false
ssao_enabled = true ssao_enabled = true
ssil_enabled = true ssil_enabled = false
sdfgi_enabled = true sdfgi_enabled = false
[sub_resource type="BoxShape3D" id="BoxShape3D_arao0"] [sub_resource type="BoxShape3D" id="BoxShape3D_arao0"]
size = Vector3(15, 20, 0.1) size = Vector3(15, 20, 0.1)
+1 -1
View File
@@ -12,7 +12,7 @@ var _camera: Camera3D
func _ready() -> void: func _ready() -> void:
var xr_interface := XRServer.find_interface("OpenXR") var xr_interface := XRServer.find_interface("OpenXR")
if xr_interface and xr_interface.is_initialized(): if xr_interface and xr_interface.is_initialized():
SweetLogger.warning("{0} disabled - this instance is the VR client", [name]) SweetLogger.debug("{0} disabled - this instance is the VR client", [name])
return return
if not _players: if not _players:
SweetLogger.warning("{0} could not resolve players_path {1}", [name, players_path]) SweetLogger.warning("{0} could not resolve players_path {1}", [name, players_path])