Allow_object_decoding = true - makes components hide global script class

Godot Version

Godot Engine v4.3.stable.steam.77dcf97d8

Question

I have a Player scene that is instantiated on peer_connected signal. That Player scene has a script containing an RPC function called “spawn” that takes another scene as an argument called Role. That Role scene contains all role specific logic, like models, animations and things each role can do. By things each role can do I mean each role has different components, for example most of them have Health Component and Death Component cause I wanted them to be damaged and die, but some of them have Inventory Component while others don’t cause I don’t want them to be able to pick up stuff. Good old Godot composition approach.

To make it all work, I need this flag to be enabled when intializing the server & clients:

multiplayer.allow_object_decoding = true

Because if I don’t, I cannot pass custom scenes as parameters in RPC methods because you get an error as:

Cannot convert argument X from Object to Object

The problem is - if I set this flag to true, I get for example this error:

Parse Error: Class "HealthComponent" hides a global script class.

The reason why it is HealthComponent specifically is because it is the first that happens to be in the hierarchy and has a custom class_name, that is happening for ALL components inside the role scene that have the class_name defined.

Now I know what you’re thinking - this guy probably has these somewhere in the global load or redefines a class_name in a different class - that is NOT the case. I definitely, 100% don’t have a duplicate class_name or any global load conflicts.

That is purely because of that flag, everything works fine without this flag as long as I don’t pass custom scenes as parameters in RPC calls. The problem is I want to pass custom scenes as parameters in RPC methods AND I want the convenience of having my own custom classes.

Is there really no way to have both? This feels like a really silly problem to face. Do I need to extract all custom classes from scenes I want to pass as an argument in RPC methods or get rid off the class_names, OR - is there another way and I’m just missing something?

What exactly are you passing? Is it a head node that has children?

WARNING :warning:

Typically allowing object decoding is very bad as it will expose you to remote code injection.

Another downside is that you could be sending a lot of data this way.

Typically you could use non-object parameters of a custom spawn function of the MultiplayerSpawner to build your scene objects.

If the scene is static the MultiplayerSpawner can watch for your tscn files to spawn them remotely.

Anyway, your problem sounds kind of weird. What I might do is turn it into a packed scene and unpack it on the other end.

var scene = PackedScene.new()
var packed = scene.pack(player)
spawn(packed)

@rpc(...)
func spawn( packedplayer: PackedScene):
  var player = packedplayer.instanciate()
  ...