Is it possible to use low-level networking along with RPC system in the same peer?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Xrayez

To enable networking, one has to provide networking peer to the SceneTree, mostly by initializing NetworkedMultiplayerENet for creating servers and clients and be able to use high-level networking capabilities. Is it possible to use such a peer to do low-level networking along with RPC system as well (since it inherits PacketPeer)? I mean something like this:

func _process(delta):
    var peer = get_tree().network_peer
    if peer:
        if is_server():
            for peer_id in players:
                if buffer.size():
                    multiplayer.send_bytes(packet, peer_id)
                    buffer.resize(0)
        else if is_client():
            while peer.get_available_packet_count():
                var packet = peer.get_packet()

The reason I’m asking is that I stumbled upon a problem sending large data to network peers (in order to sync game world). The data size can range from 500kb to 5mb.

I tried to call RPC method with my data being nested Dictionaries with values including PoolByteArrays, but the client hangs. The reason for this is probably that the packet size might be too big to be handled by RPC system… Do I have to create additional PacketPeerUDP or something similar for handling large data transfering? I’m somewhat new to networking so feel free to enlighten me on the topic.

I would always chunk the data when udp is involved and if it exeeds lets say 255 bytes.
But on the other hand, since we have enet, maybe try to “reliably” send your data.
Try to also compress your data first.

David Krause | 2018-07-09 10:33

Oh yeah I’ve even compressed my data but it still exceeds packet size. Seems like data chunking is the most logical solution… could probably use high-level networking for that too. Need to read up on the topic more.

Xrayez | 2018-07-09 10:38

:bust_in_silhouette: Reply From: hungrymonkey

Yes, Godot master has a major change in its api.

Faless introduce Mutiplayer api. Multiplayer api have a function call send_bytes that lets you send raw packets. You can receive it with network_peer_packet signal

Somehow I overlooked the network_peer_packet signal… I’ve probably got confused with default networking implementation in the SceneTree and MultiplayerAPI.

I’ve connected the signal and can freely send bytes and receive them on clients now, thanks for pointing that out!

Xrayez | 2018-07-19 18:25

:bust_in_silhouette: Reply From: Xrayez

Thanks to @hungrymonkey I’ve come up with something like this:

# Server/client
func _ready(delta):
    multiplayer.connect("network_peer_packet", self, "_on_packet_received")
    multiplayer.send_bytes(PoolByteArray([0, 1, 2, 3]))

# Client/server
func _on_packet_received(id, packet):
    print(packet)

I’ve also tried to send packets on an even lower level:

get_tree().network_peer.put_packet(packet)

In the network_peer_packet callback when trying to receive packets on client I got errors like:

ERROR: _process_get_node: Condition ' !F ' is true. returned: __null
   At: core/io/multiplayer_api.cpp:247
ERROR: _process_packet: Condition ' node == __null ' is true.
   At: core/io/multiplayer_api.cpp:187

Which is most likely expected because I’m trying to mix different APIs or whatever… Anyway since there’s send_bytes introduced I don’t think I need to go that low.