sending variable data from server to a client

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

i’m not sure how to retrieve data from server as a client, or rather send data from server to a certain client

on the server side, in script World.gd I have this function, here i spawn a player (and that works fine)

func spawn_player(spawn_pos, id):
  var player = Player.instance()
  player.position = spawn_pos
  player.name = String(id)
  player.set_network_master(id)
  $Players.add_child(player)

now in that function I want to send data from a global variable “player_list” to the player who just spawned

how would I approach this?

alright I’ve done some research and now I’m even more confused
I can successfully send data from client to server, but I get error if i try to send from server to client
for example:
on my server I have function:

remote func test(t):
  print(t)

and from my client I send:

rpc_id(1, "test", "Hello")

and it works fine

but if I put my test function on client, and send:

rpc_id(id, "test", "Hello")

from the server, it gives me error:

ERROR: Node not found: World.
At: scene/main/node.cpp:1381
ERROR: _process_get_node: Failed to get path from RPC: World.
At: core/io/multiplayer_api.cpp:256
ERROR: Invalid packet received. Requested node was not found.
At: core/io/multiplayer_api.cpp:204

Tova | 2020-03-21 17:00

and yes I made sure both client and server have matching nodes

Tova | 2020-03-21 17:01

:bust_in_silhouette: Reply From: Sween123

Networking can be quite confusing when we just get started. Same for me.
So yeah, rpc is a good way Godot provides that allows you to remote call a function, that’s great. However, it needs both sides scenes structures to be exactly the same, including the names.
That may be okay, but sometimes we may prefer using two different scenes structures for the server and the client so it will be convenient. Keeping everything the same can restrict us a lot.
So, actually you don’t have to keep the nodes the same, except the root node. For example, you have the node WORLD as the root, keep the name the same on both sides, and put two functions like send_data_to(id, data) and data_received(data). For function data_received(data) remeber to add remote, like this: remote function data_received(data)
You only need the keep the name “WORLD” the same, inside the sciripts, you can do whatever you want, But whenever we send or receive data, we go through the node WORLD.
Without directly remote call a function inside the scene, this may seem to be a little bit inconvenient, but it’s actually okay, it works quite well without needing to worry about keeping the scenes structures the same on both side and that kind of errors.
So to help to control how data comes and goes through just two functions, actually we can add data_received(data) in different scenes too, except that these functions are not for remote calls. To send a data, you can do it like this: data = {"path": "/root/WORLD/Player", "Type": "Position Update", "Position": Player.position} . Inside the function data_received(data) you can do it like this: if data.has("path"): get_node(data.path).data_received(data) so the data will be send to the scenes you want, and so we don’t have to do everything within just one script that is attached to the node WORLD.
Also, here’s how I set up networks of server and clients, it might help:
For server:

var ENET = NetworkedMultiplayerENet.new()
ENET.create_server(PORT, MAX_PLAYER_NUMBER)
get_tree().set_network_peer(ENET)

For client:

var ENET = NetworkedMultiplayerENet.new()
ENET.create_client(SERVER_IP, PORT)
get_tree().set_network_peer(ENET)

To send data, we need to use rpc function.
So:

function send_data_to(id, data):
  rpc_id(id, "data_received", data)

For the same function on client side, you can just replace the id to 1, which means the server. Also, don’t directly send data from client to client, try to go through the server first, because server is there to keep things under control and keep data flow in order.