multyplayer
This commit is contained in:
+10
-5
@@ -54,6 +54,12 @@ func _on_body_entered(body: Node3D) -> void:
|
||||
if _combining or body == _item:
|
||||
return
|
||||
|
||||
# Combining is a world-state change: only the server/offline host runs it.
|
||||
# (Clients never have the base item snapped, so their zone won't monitor, but
|
||||
# guard explicitly in case of overlap during authority handoff.)
|
||||
if not NetworkManager.owns_world():
|
||||
return
|
||||
|
||||
var other := _find_combinable(body)
|
||||
if not other:
|
||||
return
|
||||
@@ -75,11 +81,9 @@ func _combine(other_body: Node3D, result: PackedScene) -> void:
|
||||
_combining = false
|
||||
return
|
||||
|
||||
# Spawn the result at the base item's location, in world space.
|
||||
# Spawn the result (networked) at the base item's location, in world space.
|
||||
var base_transform := _item.global_transform
|
||||
var result_instance: Node3D = result.instantiate()
|
||||
_item.get_tree().current_scene.add_child(result_instance)
|
||||
result_instance.global_transform = base_transform
|
||||
var result_instance := NetworkManager.spawn_item(result.resource_path, base_transform)
|
||||
|
||||
# Free the base item and consume the incoming item.
|
||||
snap_zone.drop_object()
|
||||
@@ -90,7 +94,8 @@ func _combine(other_body: Node3D, result: PackedScene) -> void:
|
||||
other_body.queue_free()
|
||||
|
||||
# Snap the result into the now-empty zone.
|
||||
snap_zone.pick_up_object(result_instance)
|
||||
if result_instance:
|
||||
snap_zone.pick_up_object(result_instance)
|
||||
|
||||
|
||||
# Find a CombinableItem among the direct children of [param node].
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
class_name NetPickable
|
||||
extends Node
|
||||
|
||||
## Networks an XRToolsPickable (RigidBody3D). Default authority is the server,
|
||||
## which simulates free items and syncs their transform. Grabbing an item with a
|
||||
## hand transfers authority to the grabbing client (its local kinematic grab
|
||||
## driver then drives the synced transform); releasing returns authority and the
|
||||
## throw velocity to the server. Non-authority peers keep the body frozen and
|
||||
## follow the synced transform, so only one machine ever simulates an item.
|
||||
|
||||
@onready var _item: XRToolsPickable = get_parent() as XRToolsPickable
|
||||
|
||||
var net_held_by := 0 # peer id currently holding (0 = free); kept consistent via NetworkManager
|
||||
var _was_authority := true
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not _item:
|
||||
push_error("NetPickable must be a child of an XRToolsPickable")
|
||||
return
|
||||
_item.grabbed.connect(_on_grabbed)
|
||||
_item.released.connect(_on_released)
|
||||
_was_authority = _item.is_multiplayer_authority()
|
||||
_apply_authority_state()
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if not NetworkManager.is_online():
|
||||
return
|
||||
var mine := _item.is_multiplayer_authority()
|
||||
if mine != _was_authority:
|
||||
_was_authority = mine
|
||||
_apply_authority_state()
|
||||
|
||||
|
||||
# Configure physics for whether we own this item or merely mirror it.
|
||||
func _apply_authority_state() -> void:
|
||||
if not _item:
|
||||
return
|
||||
if _item.is_multiplayer_authority():
|
||||
# We own physics: simulate the item whenever it is not held.
|
||||
if not _item.is_picked_up():
|
||||
_item.freeze = false
|
||||
else:
|
||||
# Someone else owns it: follow the synced transform kinematically.
|
||||
_item.freeze = true
|
||||
_item.freeze_mode = RigidBody3D.FREEZE_MODE_KINEMATIC
|
||||
|
||||
|
||||
func _on_grabbed(_pickable: Node3D, by: Node3D) -> void:
|
||||
if not NetworkManager.is_online():
|
||||
return
|
||||
# Only hand grabs transfer authority; snap-zone grabs are server-driven.
|
||||
if not (by is XRToolsFunctionPickup):
|
||||
return
|
||||
NetworkManager.request_item_authority.rpc_id(1, _item.get_path())
|
||||
|
||||
|
||||
func _on_released(_pickable: Node3D, by: Node3D) -> void:
|
||||
if not NetworkManager.is_online():
|
||||
return
|
||||
if not (by is XRToolsFunctionPickup):
|
||||
return
|
||||
NetworkManager.release_item_authority.rpc_id(1, _item.get_path(), _item.linear_velocity, _item.angular_velocity)
|
||||
@@ -0,0 +1 @@
|
||||
uid://6n784li8n5ck
|
||||
Reference in New Issue
Block a user