Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0af0c1bfc1 | |||
| 61ea80b933 |
+3
-3
@@ -85,7 +85,7 @@ func _on_picked_up(_p) -> void:
|
|||||||
return
|
return
|
||||||
if NetworkManager.is_online():
|
if NetworkManager.is_online():
|
||||||
NetworkManager.log_line("Grabbed %s by hand, requesting authority" % _pickable.name)
|
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_from(_pickable.get_path())
|
||||||
|
|
||||||
|
|
||||||
func _on_dropped(_p) -> void:
|
func _on_dropped(_p) -> void:
|
||||||
@@ -95,6 +95,6 @@ func _on_dropped(_p) -> void:
|
|||||||
return
|
return
|
||||||
if NetworkManager.is_online():
|
if NetworkManager.is_online():
|
||||||
NetworkManager.log_line("Dropped %s, reporting release to server" % _pickable.name)
|
NetworkManager.log_line("Dropped %s, reporting release to server" % _pickable.name)
|
||||||
NetworkManager.release_item_authority.rpc_id(
|
NetworkManager.release_item_authority_from(
|
||||||
1, _pickable.get_path(), _pickable.linear_velocity, _pickable.angular_velocity
|
_pickable.get_path(), _pickable.linear_velocity, _pickable.angular_velocity
|
||||||
)
|
)
|
||||||
|
|||||||
+54
-13
@@ -165,14 +165,30 @@ func _gate_station(node: Node) -> void:
|
|||||||
|
|
||||||
# --- Item grab-authority transfer -----------------------------------------
|
# --- Item grab-authority transfer -----------------------------------------
|
||||||
|
|
||||||
## A client (or host) requests authority over an item it just grabbed. Runs on
|
## Called by NetPickable when this peer grabs an item by hand. Godot rejects
|
||||||
## the server. If the item was snapped into a station, the station releases it
|
## rpc_id() targeting your own peer id ("RPC on yourself is not allowed"), so
|
||||||
## so the grabber cleanly takes ownership.
|
## when we ARE the server this runs the logic directly instead of round-
|
||||||
|
## tripping an RPC to ourselves — otherwise every host-side grab/drop was
|
||||||
|
## silently failing to run its server-side half (no denial checks, and
|
||||||
|
## crucially no auto-snap-into-station on release).
|
||||||
|
func request_item_authority_from(item_path: NodePath) -> void:
|
||||||
|
if is_server():
|
||||||
|
_grant_or_reject_item_authority(item_path, multiplayer.get_unique_id())
|
||||||
|
else:
|
||||||
|
_request_item_authority_rpc.rpc_id(1, item_path)
|
||||||
|
|
||||||
|
|
||||||
@rpc("any_peer", "reliable")
|
@rpc("any_peer", "reliable")
|
||||||
func request_item_authority(item_path: NodePath) -> void:
|
func _request_item_authority_rpc(item_path: NodePath) -> void:
|
||||||
if not is_server():
|
if not is_server():
|
||||||
return
|
return
|
||||||
var sender := multiplayer.get_remote_sender_id()
|
_grant_or_reject_item_authority(item_path, multiplayer.get_remote_sender_id())
|
||||||
|
|
||||||
|
|
||||||
|
## Runs on the server (called directly if the requester IS the server, or via
|
||||||
|
## the RPC above otherwise). If the item was snapped into a station, the
|
||||||
|
## station releases it so the grabber cleanly takes ownership.
|
||||||
|
func _grant_or_reject_item_authority(item_path: NodePath, sender: int) -> void:
|
||||||
var item := get_node_or_null(item_path)
|
var item := get_node_or_null(item_path)
|
||||||
if item:
|
if item:
|
||||||
var np := item.get_node_or_null("NetPickable")
|
var np := item.get_node_or_null("NetPickable")
|
||||||
@@ -180,7 +196,7 @@ func request_item_authority(item_path: NodePath) -> void:
|
|||||||
# 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])
|
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_to(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])
|
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
|
||||||
@@ -190,14 +206,27 @@ func request_item_authority(item_path: NodePath) -> void:
|
|||||||
_release_from_snap_zones(item)
|
_release_from_snap_zones(item)
|
||||||
|
|
||||||
|
|
||||||
## A player releases an item, forwarding its throw velocity so the server can
|
## Called by NetPickable when this peer releases an item, forwarding its throw
|
||||||
## resume simulating it. Runs on the server. If released next to a station, the
|
## velocity so the server can resume simulating it. Same self-RPC issue as
|
||||||
## server snaps it in (server-authoritative placement).
|
## above: runs directly if we're the server.
|
||||||
|
func release_item_authority_from(item_path: NodePath, lin: Vector3, ang: Vector3) -> void:
|
||||||
|
if is_server():
|
||||||
|
_do_release_item_authority(item_path, lin, ang, multiplayer.get_unique_id())
|
||||||
|
else:
|
||||||
|
_release_item_authority_rpc.rpc_id(1, item_path, lin, ang)
|
||||||
|
|
||||||
|
|
||||||
@rpc("any_peer", "reliable")
|
@rpc("any_peer", "reliable")
|
||||||
func release_item_authority(item_path: NodePath, lin: Vector3, ang: Vector3) -> void:
|
func _release_item_authority_rpc(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()])
|
_do_release_item_authority(item_path, lin, ang, multiplayer.get_remote_sender_id())
|
||||||
|
|
||||||
|
|
||||||
|
## Runs on the server. If released next to a station, the server snaps it in
|
||||||
|
## (server-authoritative placement).
|
||||||
|
func _do_release_item_authority(item_path: NodePath, lin: Vector3, ang: Vector3, sender: int) -> void:
|
||||||
|
log_line("release_item_authority: %s released by peer %d" % [str(item_path), sender])
|
||||||
_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:
|
||||||
@@ -253,10 +282,22 @@ func _set_item_authority(item_path: NodePath, peer: int) -> void:
|
|||||||
np.apply_held_state()
|
np.apply_held_state()
|
||||||
|
|
||||||
|
|
||||||
## Server tells a specific client that its optimistic grab was rejected (the
|
## Rejects peer's optimistic grab (the item was already legitimately held by
|
||||||
## item was already legitimately held by someone else). The client drops it.
|
## someone else). Same self-RPC concern: if the rejected peer is the server
|
||||||
|
## itself, apply it directly rather than rpc_id-ing ourselves.
|
||||||
|
func _force_release_item_to(peer: int, item_path: NodePath) -> void:
|
||||||
|
if peer == 1:
|
||||||
|
_do_force_release(item_path)
|
||||||
|
else:
|
||||||
|
force_release_item.rpc_id(peer, item_path)
|
||||||
|
|
||||||
|
|
||||||
@rpc("authority", "reliable")
|
@rpc("authority", "reliable")
|
||||||
func force_release_item(item_path: NodePath) -> void:
|
func force_release_item(item_path: NodePath) -> void:
|
||||||
|
_do_force_release(item_path)
|
||||||
|
|
||||||
|
|
||||||
|
func _do_force_release(item_path: NodePath) -> void:
|
||||||
log_line("force_release_item: dropping %s (server rejected our grab)" % str(item_path))
|
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"):
|
||||||
|
|||||||
Reference in New Issue
Block a user