Help syncing item pickups in multiplayer game

Godot Version

4.2

Question

Hey, I’m new so I’m really not sure of the quality of my code and I need some help syncing item pickups on all peers. So, the game is P2P and my method of syncing item pickups right now is to use a multiplayer spawner. I’m not sure how to RPC my pickups (if necessary) and I haven’t even started on dropping items, so if anybody could offer a bit of help when it comes to implementing this, I would really appreciate it.

(called in _unhandled_input)

if not is_multiplayer_authority():
		return

if event is InputEventKey:
		if Input.is_action_pressed("ui_cancel"):
			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
		if Input.is_action_just_pressed("interact"):
			var looking_at = ray.get_collider()
			if looking_at != null:
				if looking_at.is_in_group("interactable"):
					if looking_at.is_in_group("hoverable"):
						looking_at.hover()
					if looking_at.is_in_group("usable"):
							if looking_at.is_in_group("harpoongun"):
								if !armed:
									armed = true
									gun.show()
					if looking_at.is_in_group("holdable"):
						if !holding:
							pickup(looking_at.type)
					else:
						looking_at.interact.rpc(name)
		if Input.is_action_just_pressed("drop"):
			if holding:
				pass

code for the pickup itself:

func pickup(interactable):
	var held_object = interactable.instantiate()
	hold_root.add_child(held_object)
	held_object.held = true
	holding = true

BTW, looking_at.type is an exported variable that stores the packed scene of the item I want to pick up. If there’s a better way to do this PLEASE let me know!

Right now, on the hosts end, it gives joined players the item when they pick it up (I don’t yet free the picked up item), but when the host picks it up the players can’t see it.

Anyways, I would really appreciate any help offered regarding this and anything else that you would tell me to change. i.e maybe I should use class types instead of groups for selection.

pickup should be an rpc, right?

@rpc("any_peer", "call_local")
func pickup(interactable) -> void:
	var held_object = interactable.instantiate()
	hold_root.add_child(held_object)
	held_object.held = true
	holding = true

yeah, it does need to be an rpc call but there’s 2 issues,

  1. you can’t pass objects in rpc calls without disabling some godot settings which are put in place to prevent script injection or whatever
  2. I tried using a sort of work-around with an rpc call and it just doesn’t work for some reason.
var object_type
#declared as global variable

@rpc("call_local", "any_peer")
func pickup():
	if object_type != null:
		held_object = object_type.instantiate()
		hold_root.add_child(held_object)
		held_object.held = true
		holding = true
		gun.hide()

(I define object_type in the input function)

I thought it was a type? Give it a path instead

@rpc("any_peer", "call_local")
func pickup(interactable_path: String) -> void:
	var interactable = load(interactable_path)

	var held_object = interactable.instantiate()
	hold_root.add_child(held_object)
	held_object.held = true
	holding = true

Yeah, it is a type. I should have taken it in as a string, lol. Thanks, I’ll give this a try and see if it changes anything.

Yes, that worked. I feel like an idiot lol. I was exporting type as a packed scene and that’s why this wasn’t working previously. Thanks a ton!