Sending Data Between P2P Clients
Asked Answered
I

1

0

I want a veeeeery simple way for a client to request data and it to receive it.

Currently, I have an Autoload script doing all my RPC stuff (because of the whole "must have same path" rule), and my slapdash solution is as follows.

1) Use the script to make a request. This makes an RPC to the client(s) with the desired data.
2) The client(s) use the script to make another RPC to the client that requested the data.
3) The requesting client then emits a signal so the relevant script can use the data.

My problem is that each step requires its own function, and it looks disgusting. So, my question is...
.
.
Is there a way to combine these steps into one function?
.
.
The dream would be getting rid of that second step. It'd be nice to send an request RPC then get a signal with the data. No middleman.

Indetermination answered 12/8, 2023 at 9:53 Comment(0)
I
0

Ok, so I've managed to put together something that my brain can grasp better.

I have an autoload script which I'll call RelayPoint.gd

extends Node

signal data_received(data:Variant, req_id:String);

#functions go inside
var listener:Dictionary = {};

@rpc("any_peer")
func req(req_id:String, args:Array = []) -> void: #targets all clients
	if multiplayer.get_remote_sender_id() == 0: return rpc("req", req_id, args);
	if multiplayer.get_remote_sender_id() == multiplayer.get_unique_id(): return;
	
	var data = listener[req_id].callv(args);
	rpc_id(multiplayer.get_remote_sender_id(), "_emit_data", data, req_id);

@rpc("any_peer")
func req_to(target:int, req_id:String, args:Array = []) -> void: #targets specific client
	if multiplayer.get_remote_sender_id() == 0: return rpc_id(target, "req_to", target, req_id, args);
	
	var data = listener[req_id].callv(args);
	rpc_id(multiplayer.get_remote_sender_id(), "_emit_data", data, req_id);

@rpc("any_peer")
func _emit_data(data:Variant,  req_id:String = "") -> void: data_received.emit(data, req_id);

func on(listen_id:String, function:Callable) -> void:
	listener[listen_id] = function;

Essentially, you can use Server.on(id:String, function:Callable) from any script and it'll save it in a dictionary. Now from any script (even ones you didn't call Server.on() in), you can call Server.req("id_you_chose", [required, args]) to call that function. (You can also use Server.req_to() if you're requesting data from a specific peer).

To actually catch responses, you need to add Server.connect("data_received", process_data) to the relevant script's _ready() function, and add a function called process_data(), which looks like this.

extends Node

func process_data(data:Variant, req_id:String) -> void:
	match req_id:
		"id_you_chose": pass; #do whatever to the 'data' you returned  

Now any connected peer (or the host) can request data from everyone (or a specific peer) and get a response directly to them from any script.

Is this efficient? Idk. It just works. 🫤

Indetermination answered 15/8, 2023 at 0:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.