Resources serialization and sending through RPC

Godot Version

4.2

Question

I wanted to send a custom class extended from Resource through RPC but I got cast error

Shouldn’t be object from Resource serialized/deserialized by default when sending through RPC?

The docs say:

How can I serialize a Resource object and send through RPC to the client? I can use for example JSON for serialization but I want to know if there are other solutions to this, I thought I can send resources :confused:

I think the issue is that that serialization only applies to saving/loading resource to/from project files, not anywhere else. Personally I’d just serialize it manually to something convenient.

Alternatively, you can send the resource path. I do this for building in my current project - the client sends the building descriptor’s resource path in an RPC, the server checks if the player has enough resources, and then replies with the result. I have to validate that the resource exists at the given path, but otherwise it works flawlessly.

1 Like

Thanks for answer!

So… should I use Dictionary<> and JSON for serialization?

How it should looks like? I mean, Do I need to serialize data in JSON, send JSON using RPC, and parse the JSON to data? I can use Dictionary<> as data

Both are valid approaches.

Dictionary:

  • pro: Godot serializes it internally so could be less data
  • con: you’ll have to manually specify which properties to transfer

JSON:

  • pro: You can use a library that handles the whole conversion
  • con: Slightly more bytes to move

Or, since you’re working with C#, you can roll your own implementation that uses reflection to find which properties are exported and put those into a dictionary. Then do the opposite when receiving the data.

1 Like

Thank you for answer, I appreciate that!

1 Like

this is a bit silly, but I was able ti do it fairly simply by sending the contents of the tres file, saving locally and then opening. It would be nice if we could just send bytes and resourceLoader could take bytes as an arg but…
/edit (using the built in ResourceLoader and ResourceSaver handles all the [Export] reflection for you)

protected override void LoadGame(string res)
{
    ClearGame();
    GameSaveData pakSave = ResourceLoader.Load<GameSaveData>(res);
    RestoreFromSaveData(pakSave);

    string text = FileAccess.GetFileAsString(res);
    Rpc(nameof(RPCRestoreGame), new Variant[] { text });
}

[Rpc(MultiplayerApi.RpcMode.Authority, CallLocal = false, TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
void RPCRestoreGame(string text)
{
    string tmpfilepath = "user://onlinesave.tres";
    {
        using var file = FileAccess.Open(tmpfilepath, FileAccess.ModeFlags.Write);
        file.StoreString(text);
    }

    GameSaveData pakSave = ResourceLoader.Load<GameSaveData>(tmpfilepath);
    RestoreFromSaveData(pakSave);
}

Doing a bit more research this is potentially dangerous, as resource files can contain executable code. There is an addon call Godot Safe Resource Loader that may alleviate this. See https://www.youtube.com/watch?v=43BZsLZheA4

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.