Hi everyone, this is my first post here so forgive me if I'm not clear enough on my question!

In short, I am working on a multiplayer project that uses P2P multiplayer. I have got it setup and working fine and am able to spawn players to the server as well as have their animations play according to their inputs. I've been working on implementing a "pickup/drop" weapon system where if a player's ray-cast is close enough to a weapon they can pick it up and it attaches to their hand.

What I'm having an issue with is actually having the weapon attach to the players hand and the weapon be replicated for all players.

My scripts for the weapons are a slightly modified version of StayAtHomeDev's modular weapon script. Basically the weapons take the values from a 'Weapons' resource (such as the mesh) and apply it on ready.

On the weapon, there is an attached script 'InteractableWeapon.gd' that handles the picking up:

class_name InteractableWeapon
extends Interactable

#weapon scene that gets instantiated on player's hand
const NEW_WEAPON = preload("res://packed scenes/weapon_equip.tscn")

#returns the weapon type that was picked up
func get_weapon_type() -> Weapons:
	print("Picked up " + owner.WEAPON_TYPE.name)
	var weapon_type = owner.WEAPON_TYPE
	return weapon_type

#called when player uses interaction button
@rpc("any_peer", "call_local")
func pickup_weapon(hand):
	var new_weap = NEW_WEAPON.instantiate()
	hand.add_child(new_weap, true) #adds weapon to player's hand
	new_weap.WEAPON_TYPE = get_weapon_type() #assigns weapon type from weapon that was picked up
	new_weap.name = str(new_weap.WEAPON_TYPE) + str(hand.owner.name) + str(randi_range(0,1000))
	new_weap.load_weapon()
	remove_weapon() 

This script works with the players interaction ray cast script:

extends RayCast3D

@onready var prompt = $"../../../UserInterface/InteractionPrompt"

func _ready():
	add_exception(owner)
	
func _physics_process(_delta):
	if is_colliding():
		var interactable_collider = get_collider()
		if interactable_collider is Interactable:
			if !is_multiplayer_authority(): return
			prompt.text = interactable_collider.get_prompt()
			
			if Input.is_action_just_pressed(interactable_collider.prompt_action):
				interactable_collider.interact.rpc(owner)
				if interactable_collider is InteractableWeapon:
					interactable_collider.pickup_weapon.rpc(owner.right_hand)
	else:
		prompt.text = "" 

As it is now, when the player picks up the weapon it correctly adds it to the player's right hand. However, the other players don't see the instantiated weapon in the player's hand and their game crashes.
I get the error: Invalid call. Nonexistent function 'add_child' in base 'EncodedObjectAsID'.

I've tried many different things, and was able to replicate the picked up weapon for all players using a MultiplayerSpawner, but only when I add it to the world using get_tree().root.add_child(new_weap, true). When doing this, I've attempted to reparent it, but with no luck.

Any help would be greatly appreciated.

welcome to the land of rpc...
you cant send objects via rpc, especially resources.. there is a workaround i posted long time ago..
you actually can send objects, but as you saw they are encoded.. so - not usable like you want.. you need to do code gymnastics.. see link below

I assume the hand object in the rpc function is a resource?

maybe this post can make it more clear
https://godotforums.org/d/40153-help-with-byteobject-conversion-sent-over-rpc/4

    kuligs2 Thanks for replying, I will check out your post and see if I can implement a similar conversion system.

    The hand object is just a Marker3D stored in the player script. In the player scene, it's a child of the right hand bone (using a BoneAttachtment node) of the player's rig. So my idea is instantiating and adding the weapon to the hand as a child so that it follows the position of the hand.

      meloncoconutmango that is all logical, but in the rpc world you need to deserialize and serialize the objects/resources you are sending over rpc.. it takes time to wrap your head around that.. atleast it took me a while, and frankly i already forgot 😃.. thanks for forums and post not deleted, now i can look back and see how it worked 🙂