Understanding RPC implementation in a turn-based multiplayer game

Godot Version

v4.2.1.stable.official [b09f793f5]

Question

A bit of a long read, but I think context is necessary for my questions. Still learning multiplayer… Please bear with me. :smiley:

I’m working on a turn-based multiplayer game that has 2 players with 4 characters each. Currently I have this setup: upon start of the match, the host and client instantiate the 8 characters on their own respective instances. However, there are some variables that get randomized for each character upon initialization, so that needs to be synced between the host and client.

I was thinking to resolve this issue, since I’m gonna need it soon anyway, should I just create a sync function that gets called upon start of the game (after randomization of relevant stats) and after every turn occurs? I can’t wrap my head around how to implement this in code using RPCs though. Should I just let both server and client spawn their own stuff and ask the server to send an RPC to update the state of the client’s characters?

Also, while I’m here, I’d also like to ask for advice on how to implement turn queue handling. Currently, I have a working turn queueing system for all characters. (works like FF7 where a bar slowly gets filled and grants a turn when full)

But again, the filling up of the bar is handled on their own respective instances, no RPCs, (which I think should be fine, right?) and gives the turn to the first character to fill it up. Once the acting player A confirms an action, should I send an RPC to tell player B what actions need to be performed/animated/displayed? And then call the aforementioned sync function RPC to sync stats between both players?

I apologize for the wall of text, and thank you for reading through it. Looking forward to your answers, thank you!

Make name of nodes are synthorized

Name the same nodes as same name each client.
When default MultiplayerAPI received a rpc request, it will find node by its path.

RPC function define

Use @rpc before a function define to mark the function can be called by remote.
There are 3 flag types:

  • mode: authority, any_peer
  • sync: call_remote, call_local
  • transfer_mode: unreliable unreliable_ordered reliable

And channel(but i don’t know things about it).

Authority of node

You can set authority of node by set_multiplayer_authority(peer_id).
That means the peer can call remote function flagged authority of this node.
Relatively, remote function flagged any_peer can be called by any peer.

Synchronizing

When you call a rpc function flagged call_remote, it will not be called in local.
In call_local, when it be called, it also will be called in local.

Reliable and unreliable

  • reliable: Every rpc request will be received in remote
  • unreliable_ordered: Not every rpc request will be received in remote, but the order of them is still right.
  • unreliable: Not every rpc request will be received in remote and it maybe will be out of order.

Property synchronizing

Use node MultiplayerSynchronizer to make them synchornized.
It will spread values in authority peer to other peers.

For example

Server → Client: @rpc("authority", "call_remote", "reliable")
Server → Every peer: @rpc("authority", "call_local", "reliable")
Client → Server: @rpc("any_peer", "call_remote", "reliable")
Authority Client → Server: @rpc("authority", "call_remote", "reliable")

1 Like

Thank you for the summary, the examples are especially helpful!