This commit is contained in:
algodoogle
2026-07-16 22:23:33 +01:00
parent 1869dbf054
commit 4e6c645938
6 changed files with 91 additions and 12 deletions
+2 -1
View File
@@ -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
View File
@@ -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)