fix bug
This commit is contained in:
+2
-1
@@ -8,7 +8,8 @@ signal host_pressed()
|
||||
signal join_pressed(ip: String)
|
||||
signal solo_pressed()
|
||||
|
||||
var _ip := "127.0.0.1"
|
||||
#var _ip := "127.0.0.1"
|
||||
var _ip := "51.175.10.161"
|
||||
|
||||
@onready var _ip_label: Label = %IPLabel
|
||||
@onready var _status: Label = %Status
|
||||
|
||||
+59
-9
@@ -68,13 +68,20 @@ func join(address: String = "127.0.0.1", port: int = DEFAULT_PORT) -> Error:
|
||||
|
||||
## Leave the session and tear down transport.
|
||||
func leave() -> void:
|
||||
if multiplayer.multiplayer_peer:
|
||||
multiplayer.multiplayer_peer.close()
|
||||
multiplayer.multiplayer_peer = null
|
||||
_go_offline()
|
||||
log_line("Session ended")
|
||||
session_ended.emit()
|
||||
|
||||
|
||||
# Restore Godot's default OfflineMultiplayerPeer (rather than leaving the peer
|
||||
# null), so is_multiplayer_authority()/get_unique_id() keep working while we are
|
||||
# back in single-player / menu state.
|
||||
func _go_offline() -> void:
|
||||
if multiplayer.multiplayer_peer:
|
||||
multiplayer.multiplayer_peer.close()
|
||||
multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new()
|
||||
|
||||
|
||||
# --- Item spawning ---------------------------------------------------------
|
||||
|
||||
## Spawn a networked item. Server-only when online (replicates to all peers via
|
||||
@@ -108,17 +115,25 @@ func _spawn_item_from_data(data: Variant) -> Node:
|
||||
|
||||
# --- Item grab-authority transfer -----------------------------------------
|
||||
|
||||
## A client requests authority over an item it just grabbed. Runs on the server.
|
||||
## A client (or host) requests authority over an item it just grabbed. Runs on
|
||||
## the server. If the item was snapped into a station, the station releases it
|
||||
## so the grabber cleanly takes ownership.
|
||||
@rpc("any_peer", "reliable")
|
||||
func request_item_authority(item_path: NodePath) -> void:
|
||||
if not is_server():
|
||||
return
|
||||
var sender := multiplayer.get_remote_sender_id()
|
||||
# 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.
|
||||
_set_item_authority.rpc(item_path, sender)
|
||||
var item := get_node_or_null(item_path)
|
||||
if item:
|
||||
_release_from_snap_zones(item)
|
||||
|
||||
|
||||
## A client releases an item, forwarding its throw velocity so the server can
|
||||
## resume simulating it. Runs on the server.
|
||||
## A player releases an item, forwarding its throw velocity so the server can
|
||||
## resume simulating it. Runs on the server. If released next to a station, the
|
||||
## server snaps it in (server-authoritative placement).
|
||||
@rpc("any_peer", "reliable")
|
||||
func release_item_authority(item_path: NodePath, lin: Vector3, ang: Vector3) -> void:
|
||||
if not is_server():
|
||||
@@ -129,6 +144,36 @@ func release_item_authority(item_path: NodePath, lin: Vector3, ang: Vector3) ->
|
||||
item.freeze = false
|
||||
item.linear_velocity = lin
|
||||
item.angular_velocity = ang
|
||||
_try_snap_into_station(item)
|
||||
|
||||
|
||||
# All station snap zones in the world (nodes in the "station" group).
|
||||
func _station_snap_zones() -> Array:
|
||||
var zones := []
|
||||
for station in get_tree().get_nodes_in_group("station"):
|
||||
var zone = station.get_node_or_null("XRToolsSnapZone")
|
||||
if zone:
|
||||
zones.append(zone)
|
||||
return zones
|
||||
|
||||
|
||||
# If the item is snapped into any station, drop it from that station.
|
||||
func _release_from_snap_zones(item: Node) -> void:
|
||||
for zone in _station_snap_zones():
|
||||
if zone.picked_up_object == item:
|
||||
zone.drop_object()
|
||||
|
||||
|
||||
# Snap the item into the nearest empty station snap zone within grab range.
|
||||
func _try_snap_into_station(item: Node) -> void:
|
||||
if not (item is Node3D):
|
||||
return
|
||||
for zone in _station_snap_zones():
|
||||
if is_instance_valid(zone.picked_up_object):
|
||||
continue
|
||||
if zone.global_position.distance_to(item.global_position) <= zone.grab_distance:
|
||||
zone.pick_up_object(item)
|
||||
return
|
||||
|
||||
|
||||
# Server broadcasts an authority assignment so every peer agrees on who owns the
|
||||
@@ -142,6 +187,7 @@ func _set_item_authority(item_path: NodePath, peer: int) -> void:
|
||||
var np := item.get_node_or_null("NetPickable")
|
||||
if np:
|
||||
np.net_held_by = 0 if peer == 1 else peer
|
||||
np.apply_held_state()
|
||||
|
||||
|
||||
func is_server() -> bool:
|
||||
@@ -213,12 +259,12 @@ func _on_connected_to_server() -> void:
|
||||
|
||||
func _on_connection_failed() -> void:
|
||||
log_line("connection_failed")
|
||||
multiplayer.multiplayer_peer = null
|
||||
_go_offline()
|
||||
connection_failed.emit()
|
||||
|
||||
func _on_server_disconnected() -> void:
|
||||
log_line("server_disconnected")
|
||||
multiplayer.multiplayer_peer = null
|
||||
_go_offline()
|
||||
session_ended.emit()
|
||||
|
||||
|
||||
@@ -262,7 +308,11 @@ func _open_log() -> void:
|
||||
log_line("=== NetworkManager log (pid %d) ===" % OS.get_process_id())
|
||||
|
||||
func log_line(s: String) -> void:
|
||||
var line := "[NET %d] %s" % [multiplayer.get_unique_id() if multiplayer.multiplayer_peer else 0, s]
|
||||
var id := 0
|
||||
var p := multiplayer.multiplayer_peer
|
||||
if p != null and p.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED:
|
||||
id = multiplayer.get_unique_id()
|
||||
var line := "[NET %d] %s" % [id, s]
|
||||
print(line)
|
||||
if _log_file:
|
||||
_log_file.store_line(line)
|
||||
|
||||
@@ -24,6 +24,17 @@ func _ready() -> void:
|
||||
_apply_authority_state()
|
||||
|
||||
|
||||
## Enable the item only where it is free or where we are its current holder, so
|
||||
## a peer's snap zone / hand never grabs an item another peer is holding. Called
|
||||
## by NetworkManager whenever net_held_by changes. Note: net_held_by is set per
|
||||
## peer by RPC (not by a synchronizer), so the holder keeps its item enabled
|
||||
## while everyone else disables their copy.
|
||||
func apply_held_state() -> void:
|
||||
if not _item:
|
||||
return
|
||||
_item.enabled = net_held_by == 0 or net_held_by == multiplayer.get_unique_id()
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if not NetworkManager.is_online():
|
||||
return
|
||||
|
||||
@@ -26,7 +26,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5270121, 0)
|
||||
collision_layer = 65536
|
||||
collision_mask = 65536
|
||||
script = ExtResource("1_dlkho")
|
||||
snap_mode = 1
|
||||
snap_mode = 0
|
||||
metadata/_custom_type_script = "uid://cquqe4f1m1sw6"
|
||||
|
||||
[node name="CollisionShape3D2" type="CollisionShape3D" parent="XRToolsSnapZone" unique_id=969340130]
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5270121, 0)
|
||||
collision_layer = 65536
|
||||
collision_mask = 65536
|
||||
script = ExtResource("2_er1dp")
|
||||
snap_mode = 1
|
||||
snap_mode = 0
|
||||
metadata/_custom_type_script = "uid://cquqe4f1m1sw6"
|
||||
|
||||
[node name="CollisionShape3D2" type="CollisionShape3D" parent="XRToolsSnapZone" unique_id=370920392]
|
||||
|
||||
@@ -23,6 +23,7 @@ func _ready() -> void:
|
||||
NetworkManager.player_left.connect(_on_player_left)
|
||||
NetworkManager.session_started.connect(_on_session_started)
|
||||
NetworkManager.connection_failed.connect(_on_connection_failed)
|
||||
NetworkManager.session_ended.connect(_on_session_ended)
|
||||
_menu.host_pressed.connect(_on_menu_host)
|
||||
_menu.join_pressed.connect(_on_menu_join)
|
||||
_menu.solo_pressed.connect(_on_menu_solo)
|
||||
@@ -66,6 +67,9 @@ func _on_session_started(is_server: bool) -> void:
|
||||
if not is_server:
|
||||
# Connected to a host as a client.
|
||||
_menu.hide_menu()
|
||||
# Stations are server-authoritative: clients must not run snap zones, or
|
||||
# they create divergent local copies of snapped items.
|
||||
_disable_client_snap_zones()
|
||||
|
||||
|
||||
func _on_connection_failed() -> void:
|
||||
@@ -74,6 +78,19 @@ func _on_connection_failed() -> void:
|
||||
_menu.show_menu()
|
||||
|
||||
|
||||
# The client lost the server (or left): reload the scene to return to a clean
|
||||
# main-menu state.
|
||||
func _on_session_ended() -> void:
|
||||
get_tree().reload_current_scene.call_deferred()
|
||||
|
||||
|
||||
func _disable_client_snap_zones() -> void:
|
||||
for station in get_tree().get_nodes_in_group("station"):
|
||||
var zone = station.get_node_or_null("XRToolsSnapZone")
|
||||
if zone:
|
||||
zone.enabled = false
|
||||
|
||||
|
||||
# --- Player / item spawning ------------------------------------------------
|
||||
|
||||
func _on_player_joined(peer_id: int) -> void:
|
||||
|
||||
Reference in New Issue
Block a user