Merge branch 'multi2' of https://git.offcoursegames.com/JonShard/VRyHungry1 into multi2
This commit is contained in:
@@ -61,6 +61,8 @@ func _on_picked_up(_p) -> void:
|
|||||||
var by := _pickable.get_picked_up_by()
|
var by := _pickable.get_picked_up_by()
|
||||||
if not (by is XRToolsFunctionPickup):
|
if not (by is XRToolsFunctionPickup):
|
||||||
return
|
return
|
||||||
|
if NetworkManager.is_online():
|
||||||
|
NetworkManager.log_line("Grabbed %s by hand, requesting authority" % _pickable.name)
|
||||||
NetworkManager.request_item_authority.rpc_id(1, _pickable.get_path())
|
NetworkManager.request_item_authority.rpc_id(1, _pickable.get_path())
|
||||||
|
|
||||||
|
|
||||||
@@ -69,6 +71,8 @@ func _on_dropped(_p) -> void:
|
|||||||
# apply_held_state() losing authority (see above) must not re-report.
|
# apply_held_state() losing authority (see above) must not re-report.
|
||||||
if not is_multiplayer_authority():
|
if not is_multiplayer_authority():
|
||||||
return
|
return
|
||||||
|
if NetworkManager.is_online():
|
||||||
|
NetworkManager.log_line("Dropped %s, reporting release to server" % _pickable.name)
|
||||||
NetworkManager.release_item_authority.rpc_id(
|
NetworkManager.release_item_authority.rpc_id(
|
||||||
1, _pickable.get_path(), _pickable.linear_velocity, _pickable.angular_velocity
|
1, _pickable.get_path(), _pickable.linear_velocity, _pickable.angular_velocity
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ func spawn_item(scene_path: String, xform: Transform3D, node_name: String = "",
|
|||||||
if is_online() and not is_server():
|
if is_online() and not is_server():
|
||||||
return null
|
return null
|
||||||
var data := {"scene": scene_path, "xform": xform, "name": node_name, "props": props}
|
var data := {"scene": scene_path, "xform": xform, "name": node_name, "props": props}
|
||||||
|
var via := "spawner" if (is_online() and _items_spawner) else "offline"
|
||||||
|
log_line("spawn_item: %s (name=%s, via=%s)" % [scene_path.get_file(), node_name, via])
|
||||||
if is_online() and _items_spawner:
|
if is_online() and _items_spawner:
|
||||||
return _items_spawner.spawn(data)
|
return _items_spawner.spawn(data)
|
||||||
# Offline: instantiate directly under the registered content root, or (for
|
# Offline: instantiate directly under the registered content root, or (for
|
||||||
@@ -120,6 +122,7 @@ func spawn_item(scene_path: String, xform: Transform3D, node_name: String = "",
|
|||||||
## the single seam for destroying spawned items (works offline too).
|
## the single seam for destroying spawned items (works offline too).
|
||||||
func despawn_item(node: Node) -> void:
|
func despawn_item(node: Node) -> void:
|
||||||
if owns_world() and is_instance_valid(node):
|
if owns_world() and is_instance_valid(node):
|
||||||
|
log_line("despawn_item: %s" % node.name)
|
||||||
node.queue_free()
|
node.queue_free()
|
||||||
|
|
||||||
|
|
||||||
@@ -157,6 +160,7 @@ func _gate_station(node: Node) -> void:
|
|||||||
child.enabled = false
|
child.enabled = false
|
||||||
child.set_process(false)
|
child.set_process(false)
|
||||||
node.set_process(false)
|
node.set_process(false)
|
||||||
|
log_line("gated station (non-owner peer): %s" % node.name)
|
||||||
|
|
||||||
|
|
||||||
# --- Item grab-authority transfer -----------------------------------------
|
# --- Item grab-authority transfer -----------------------------------------
|
||||||
@@ -175,8 +179,10 @@ func request_item_authority(item_path: NodePath) -> void:
|
|||||||
if np and np.net_held_by != 0 and np.net_held_by != sender:
|
if np and np.net_held_by != 0 and np.net_held_by != sender:
|
||||||
# Already legitimately held by a different live peer: reject the
|
# Already legitimately held by a different live peer: reject the
|
||||||
# requester's optimistic client-side grab instead of stealing it.
|
# requester's optimistic client-side grab instead of stealing it.
|
||||||
|
log_line("request_item_authority: DENIED %s to peer %d (already held by %d)" % [item.name, sender, np.net_held_by])
|
||||||
force_release_item.rpc_id(sender, item_path)
|
force_release_item.rpc_id(sender, item_path)
|
||||||
return
|
return
|
||||||
|
log_line("request_item_authority: granting %s to peer %d" % [str(item.name) if item else str(item_path), sender])
|
||||||
# Assign authority + held state first (disables the item on the server so its
|
# Assign authority + held state first (disables the item on the server so its
|
||||||
# snap zone won't re-grab it), then release it from any station.
|
# snap zone won't re-grab it), then release it from any station.
|
||||||
_set_item_authority.rpc(item_path, sender)
|
_set_item_authority.rpc(item_path, sender)
|
||||||
@@ -191,6 +197,7 @@ func request_item_authority(item_path: NodePath) -> void:
|
|||||||
func release_item_authority(item_path: NodePath, lin: Vector3, ang: Vector3) -> void:
|
func release_item_authority(item_path: NodePath, lin: Vector3, ang: Vector3) -> void:
|
||||||
if not is_server():
|
if not is_server():
|
||||||
return
|
return
|
||||||
|
log_line("release_item_authority: %s released by peer %d" % [str(item_path), multiplayer.get_remote_sender_id()])
|
||||||
_set_item_authority.rpc(item_path, 1)
|
_set_item_authority.rpc(item_path, 1)
|
||||||
var item := get_node_or_null(item_path)
|
var item := get_node_or_null(item_path)
|
||||||
if item is RigidBody3D:
|
if item is RigidBody3D:
|
||||||
@@ -226,6 +233,7 @@ func _try_snap_into_station(item: Node) -> void:
|
|||||||
if is_instance_valid(zone.picked_up_object):
|
if is_instance_valid(zone.picked_up_object):
|
||||||
continue
|
continue
|
||||||
if zone.global_position.distance_to(item.global_position) <= zone.grab_distance:
|
if zone.global_position.distance_to(item.global_position) <= zone.grab_distance:
|
||||||
|
log_line("snapped %s into %s" % [item.name, zone.get_parent().name])
|
||||||
zone.pick_up_object(item)
|
zone.pick_up_object(item)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -237,6 +245,7 @@ func _set_item_authority(item_path: NodePath, peer: int) -> void:
|
|||||||
var item := get_node_or_null(item_path)
|
var item := get_node_or_null(item_path)
|
||||||
if not item:
|
if not item:
|
||||||
return
|
return
|
||||||
|
log_line("_set_item_authority: %s -> peer %d" % [item.name, peer])
|
||||||
item.set_multiplayer_authority(peer) # recursive: item + synchronizer + NetPickable
|
item.set_multiplayer_authority(peer) # recursive: item + synchronizer + NetPickable
|
||||||
var np := item.get_node_or_null("NetPickable")
|
var np := item.get_node_or_null("NetPickable")
|
||||||
if np:
|
if np:
|
||||||
@@ -248,6 +257,7 @@ func _set_item_authority(item_path: NodePath, peer: int) -> void:
|
|||||||
## item was already legitimately held by someone else). The client drops it.
|
## item was already legitimately held by someone else). The client drops it.
|
||||||
@rpc("authority", "reliable")
|
@rpc("authority", "reliable")
|
||||||
func force_release_item(item_path: NodePath) -> void:
|
func force_release_item(item_path: NodePath) -> void:
|
||||||
|
log_line("force_release_item: dropping %s (server rejected our grab)" % str(item_path))
|
||||||
var item := get_node_or_null(item_path)
|
var item := get_node_or_null(item_path)
|
||||||
if item and item.has_method("drop"):
|
if item and item.has_method("drop"):
|
||||||
item.drop()
|
item.drop()
|
||||||
@@ -283,6 +293,7 @@ func submit_work(station_path: NodePath, amount: float) -> void:
|
|||||||
return
|
return
|
||||||
var station := get_node_or_null(station_path)
|
var station := get_node_or_null(station_path)
|
||||||
if station and station.has_method("add_work"):
|
if station and station.has_method("add_work"):
|
||||||
|
log_line("submit_work: peer %d contributed %.2f to %s" % [multiplayer.get_remote_sender_id(), amount, station.name])
|
||||||
station.add_work(multiplayer.get_remote_sender_id(), amount)
|
station.add_work(multiplayer.get_remote_sender_id(), amount)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ mesh = SubResource("BoxMesh_24d3s")
|
|||||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1177077250]
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1177077250]
|
||||||
environment = SubResource("Environment_bvwq1")
|
environment = SubResource("Environment_bvwq1")
|
||||||
|
|
||||||
[node name="WorldContent" type="Node3D" parent="."]
|
[node name="WorldContent" type="Node3D" parent="." unique_id=291550153]
|
||||||
|
|
||||||
[node name="Players" type="Node3D" parent="."]
|
[node name="Players" type="Node3D" parent="." unique_id=1595463693]
|
||||||
|
|
||||||
[node name="ItemsSpawner" type="MultiplayerSpawner" parent="."]
|
[node name="ItemsSpawner" type="MultiplayerSpawner" parent="." unique_id=627119248]
|
||||||
spawn_path = NodePath("../WorldContent")
|
spawn_path = NodePath("../WorldContent")
|
||||||
|
|
||||||
[node name="PlayersSpawner" type="MultiplayerSpawner" parent="."]
|
[node name="PlayersSpawner" type="MultiplayerSpawner" parent="." unique_id=106645565]
|
||||||
_spawnable_scenes = PackedStringArray("res://Player/net_player.tscn")
|
_spawnable_scenes = PackedStringArray("res://Player/net_player.tscn")
|
||||||
spawn_path = NodePath("../Players")
|
spawn_path = NodePath("../Players")
|
||||||
|
|||||||
@@ -31,11 +31,27 @@ func _ready() -> void:
|
|||||||
NetworkManager.session_ended.connect(_on_session_ended)
|
NetworkManager.session_ended.connect(_on_session_ended)
|
||||||
NetworkManager.connection_failed.connect(_on_connection_failed)
|
NetworkManager.connection_failed.connect(_on_connection_failed)
|
||||||
|
|
||||||
# Offline (single player / dev run): owns_world() is already true, so
|
# world_ready() is what actually calls host()/join() (or the cmdline
|
||||||
# populate immediately. Online host case is handled by session_started.
|
# equivalent). Populating before this point is wrong for EVERY case, not
|
||||||
|
# just offline: is_online() is still false until host()/join() runs, so
|
||||||
|
# owns_world() would read true for a joining client too, and it would
|
||||||
|
# build its own local copy instead of receiving the server's via the
|
||||||
|
# spawner. host() emits session_started synchronously, which populates
|
||||||
|
# via _on_session_started below; the explicit call after world_ready()
|
||||||
|
# only matters for the case where neither host() nor join() ran (no
|
||||||
|
# pending session, no cmdline args) — running this scene directly offline.
|
||||||
|
NetworkManager.world_ready()
|
||||||
_populate_world_if_owner()
|
_populate_world_if_owner()
|
||||||
|
|
||||||
NetworkManager.world_ready()
|
get_tree().create_timer(3.0).timeout.connect(_log_world_state)
|
||||||
|
|
||||||
|
|
||||||
|
# Temporary-ish sanity check: confirms WorldContent actually ended up
|
||||||
|
# populated on this peer (whether by spawning it or by receiving it via
|
||||||
|
# replication), so a silent replication failure shows up in the net log
|
||||||
|
# instead of just an empty-looking world.
|
||||||
|
func _log_world_state() -> void:
|
||||||
|
NetworkManager.log_line("World state: WorldContent=%d children, Players=%d children" % [$WorldContent.get_child_count(), $Players.get_child_count()])
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree() -> void:
|
func _exit_tree() -> void:
|
||||||
@@ -53,10 +69,14 @@ func _populate_world_if_owner() -> void:
|
|||||||
return
|
return
|
||||||
_populated = true
|
_populated = true
|
||||||
GameManager.meals_in_play = ["hamburger"]
|
GameManager.meals_in_play = ["hamburger"]
|
||||||
for d in WorldLayout.get_stations():
|
var stations := WorldLayout.get_stations()
|
||||||
|
var items := WorldLayout.get_items()
|
||||||
|
NetworkManager.log_line("Populating world: %d stations, %d items" % [stations.size(), items.size()])
|
||||||
|
for d in stations:
|
||||||
NetworkManager.spawn_item(d["scene"], d["xform"], d["name"], d["props"])
|
NetworkManager.spawn_item(d["scene"], d["xform"], d["name"], d["props"])
|
||||||
for d in WorldLayout.get_items():
|
for d in items:
|
||||||
NetworkManager.spawn_item(d["scene"], d["xform"], d["name"], d["props"])
|
NetworkManager.spawn_item(d["scene"], d["xform"], d["name"], d["props"])
|
||||||
|
NetworkManager.log_line("World populated")
|
||||||
|
|
||||||
|
|
||||||
## Only the server (or the single offline machine) materialises player
|
## Only the server (or the single offline machine) materialises player
|
||||||
@@ -68,6 +88,7 @@ func _on_player_joined(peer_id: int) -> void:
|
|||||||
var p := PLAYER_SCENE.instantiate()
|
var p := PLAYER_SCENE.instantiate()
|
||||||
p.name = str(peer_id)
|
p.name = str(peer_id)
|
||||||
$Players.add_child(p, true)
|
$Players.add_child(p, true)
|
||||||
|
NetworkManager.log_line("Spawned avatar for peer %d" % peer_id)
|
||||||
|
|
||||||
|
|
||||||
func _on_player_left(peer_id: int) -> void:
|
func _on_player_left(peer_id: int) -> void:
|
||||||
@@ -76,11 +97,14 @@ func _on_player_left(peer_id: int) -> void:
|
|||||||
var p := $Players.get_node_or_null(str(peer_id))
|
var p := $Players.get_node_or_null(str(peer_id))
|
||||||
if p:
|
if p:
|
||||||
p.queue_free()
|
p.queue_free()
|
||||||
|
NetworkManager.log_line("Despawned avatar for peer %d" % peer_id)
|
||||||
|
|
||||||
|
|
||||||
func _on_session_ended() -> void:
|
func _on_session_ended() -> void:
|
||||||
|
NetworkManager.log_line("Session ended, returning to main menu")
|
||||||
get_tree().change_scene_to_file("res://Scenes/mainMenu.tscn")
|
get_tree().change_scene_to_file("res://Scenes/mainMenu.tscn")
|
||||||
|
|
||||||
|
|
||||||
func _on_connection_failed() -> void:
|
func _on_connection_failed() -> void:
|
||||||
|
NetworkManager.log_line("Connection failed, returning to main menu")
|
||||||
get_tree().change_scene_to_file("res://Scenes/mainMenu.tscn")
|
get_tree().change_scene_to_file("res://Scenes/mainMenu.tscn")
|
||||||
|
|||||||
Reference in New Issue
Block a user