asd
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
extends MultiplayerSynchronizer
|
||||
|
||||
## Networked sync component for a pickable item. Added as a child literally
|
||||
## named "NetPickable" (network_manager.gd's authority RPCs already expect
|
||||
## this) of every net-synced pickable, replicating its transform and held
|
||||
## state. Only the current multiplayer authority (the server while loose, or
|
||||
## whichever peer is holding it) actually simulates physics for the item;
|
||||
## every other peer freezes their local copy and just follows the synced
|
||||
## transform.
|
||||
|
||||
## 0 = loose/server-simulated; otherwise the peer id currently holding it.
|
||||
## Replicated at spawn and on change so a late joiner sees the current holder.
|
||||
var net_held_by: int = 0: set = _set_net_held_by
|
||||
|
||||
var _pickable: XRToolsPickable
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_pickable = get_parent() as XRToolsPickable
|
||||
if not _pickable:
|
||||
push_error("NetPickable must be a child of an XRToolsPickable")
|
||||
return
|
||||
_pickable.picked_up.connect(_on_picked_up)
|
||||
_pickable.dropped.connect(_on_dropped)
|
||||
# Deferred: the pickable root captures its own original_collision_mask/
|
||||
# original_collision_layer via @onready, which runs AFTER this child's
|
||||
# _ready() but BEFORE the root's _ready() body. Calling apply_held_state
|
||||
# synchronously here would freeze/mask the item before that capture runs,
|
||||
# permanently corrupting the "restore on drop" values.
|
||||
apply_held_state.call_deferred()
|
||||
|
||||
|
||||
func _set_net_held_by(value: int) -> void:
|
||||
net_held_by = value
|
||||
apply_held_state()
|
||||
|
||||
|
||||
## Puts the item in the right physics state for whether this peer currently
|
||||
## owns it. Called locally after net_held_by changes, and directly by
|
||||
## NetworkManager._set_item_authority right after an authority handoff.
|
||||
func apply_held_state() -> void:
|
||||
if not _pickable:
|
||||
return
|
||||
if not NetworkManager.is_online() or is_multiplayer_authority():
|
||||
# We own this item's simulation (offline, loose+server, or currently
|
||||
# holding it): leave physics alone, XRToolsPickable manages the rest.
|
||||
return
|
||||
# Someone else owns it: stop simulating locally, just follow the sync.
|
||||
if _pickable.is_picked_up():
|
||||
_pickable.drop()
|
||||
_pickable.freeze = true
|
||||
_pickable.freeze_mode = RigidBody3D.FREEZE_MODE_KINEMATIC
|
||||
_pickable.collision_mask = 0
|
||||
_pickable.enabled = (net_held_by == 0)
|
||||
|
||||
|
||||
## Local hand grab (not a station snap zone, which is server-only): request
|
||||
## authority immediately so the throw/drop can be reconciled, but let the grab
|
||||
## happen instantly here rather than waiting on the round trip.
|
||||
func _on_picked_up(_p) -> void:
|
||||
var by := _pickable.get_picked_up_by()
|
||||
if not (by is XRToolsFunctionPickup):
|
||||
return
|
||||
NetworkManager.request_item_authority.rpc_id(1, _pickable.get_path())
|
||||
|
||||
|
||||
func _on_dropped(_p) -> void:
|
||||
# Only forward if we're actually still the authority — a drop caused by
|
||||
# apply_held_state() losing authority (see above) must not re-report.
|
||||
if not is_multiplayer_authority():
|
||||
return
|
||||
NetworkManager.release_item_authority.rpc_id(
|
||||
1, _pickable.get_path(), _pickable.linear_velocity, _pickable.angular_velocity
|
||||
)
|
||||
Reference in New Issue
Block a user