godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.21k stars 21.04k forks source link

RPC call Autoload from server #74425

Open theromis opened 1 year ago

theromis commented 1 year ago

Godot version

4.0.stable

System information

Macos

Issue description

getting _process_rpc: RPC '_check_client_version' is not allowed on node /root/AutoloadChecker from: 721864190. Mode is 2, authority is 1. from autoload script, same logic added to scene node works fine

func _ready() -> void:
    if multiplayer.is_server():
        multiplayer.peer_connected.connect(_on_network_peer_connected)

func _exit_tree() -> void:
    if multiplayer.is_server():
        multiplayer.peer_connected.disconnect(_on_network_peer_connected)

@rpc
func _check_client_version(_host_client_version: String) -> void:
    print("_check_client_version autoload")

func _on_network_peer_connected(peer_id: int) -> void:
    _check_client_version.rpc_id(peer_id, "123")

Steps to reproduce

run example project, connect to hosted server

Minimal reproduction project

https://github.com/theromis/scene_replication

theromis commented 1 year ago

But it happens only if MultiplayerSpawner way Map loaded, if I'm disabling it, rpc works fine.

theromis commented 1 year ago

Want to share my workaround for it:

func _ready():
    if multiplayer.is_server():
        multiplayer.peer_connected.connect(_on_peer_connected)
        multiplayer.peer_disconnected.connect(_on_peer_disconnected)

func _exit_tree():
    if multiplayer.is_server():
        multiplayer.peer_connected.disconnect(_on_peer_connected)
        multiplayer.peer_disconnected.disconnect(_on_peer_disconnected)

func _on_peer_connected(peer_id: int):
    OnlineMatch._on_network_peer_connected(peer_id)
    add_player(peer_id)

func _on_peer_disconnected(peer_id: int):
    OnlineMatch._on_network_peer_disconnected(peer_id)
    del_player(peer_id)

just call this "gloabal" functions from inside of the "MultplayerSpawer" spawned level, still not sure does it solves all my rpc issues or only partially, will keep this ticket updated

HaruYou27 commented 1 year ago

The signal _on_network_peer_connected is emitted on both peer. That means your _check_client_version function also get called on server instance by the client, but the client doesn't have the authority to do so. See peer_connected signal: https://docs.godotengine.org/en/stable/classes/class_multiplayerapi.html

See RPC authority in Godot https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-rpc-config

Note: Godot high level multiplayer document is currently outdated.

theromis commented 1 year ago

@haruyou27 sorry for late reply, seems like I'm doing wrong multiplayer connections callbacks, what will be the right approach with my example?

HaruYou27 commented 1 year ago

Server peer will always has peer_id = 1. You can just stop the client from calling the rpc function.

func _on_network_peer_connected(peer_id: int) -> void:
        if peer_id == 1:
               return
    _check_client_version.rpc_id(peer_id, "123")