i need to send a node over the network (low-level enet, i.e. no RPC) from the server to the clients where the node is the game world
from my understanding what is currently availiable is the MultiplayerSynchronizer node which can sync props however i also need to be able to sync resources and objects - or basically the world itself (also, it’s high-level)
the world is entirely on the server and hence the client does not know what resources or nodes or whatever the world is to have - i intend on having them be user-made at some point
i have tried to serialise the node into a JSON string to send from the server to packet and going through the node’s props and children (and their own props and children), then deserialising it at the client and constructing the node from that - however i have doubts that this implementation would work because it does not appear to be serialising resources
serialisation code:
func node_to_dict(node: Node) -> Dictionary:
var serialised_node: Dictionary = {
"class": node.get_class(),
"properties": {},
"children": {}
}
var node_default_properties: Node = ClassDB.instantiate(node.get_class())
for property in node.get_property_list():
var property_name: String = property.name
var property_value: Variant = node.get(property_name)
var default_property_value: Variant
if (property_name == "position"
or property_name == "rotation"
or property_name == "scale"): # (i) skip the checks for position and serialise it anyways
serialised_node["properties"][property_name] = Marshalls.variant_to_base64(property_value)
elif not property_value == default_property_value:
serialised_node["properties"][property_name] = Marshalls.variant_to_base64(property_value)
node_default_properties.queue_free()
for child in node.get_children():
serialised_node["children"][child.get_name()] = node_to_dict(child)
return serialised_node
of course if there is a solution to what i’m trying to acheive that does not require the serialisation of the world that would also be fine
That only means when you save a scene or resource as their binary format scn and res respectively. They use a different binary format. The binary serialization API will still serialize any Object as shown in the Object section.
You cannot do that. Godot doesn’t allow you to send Objects through RPCs or through the MultiplayerSynchronizer. You can only send data.
You’re on the right path with node_to_dict() but it looks like you’re trying to create a generic one-size fits all approach. My recommendation is to take the problem in smaller pieces. And to use an inheritance-based approach rather than a Factory Pattern.
Pick a node you want to serialize.
Write a to_dict() function for that node.
Write a from_dict() function for that node.
Pass the Dictionary value to make sure it works.
Do the same with the next object.
Refactor those two functions into a base function that both can inherit from in a base class.
Right now you’re digging into some pretty meta functionality in Godot with get_property_list(). There are some caveats in the documentation for using it. For example if you’re using GDExtension or C# classes in a Mono build, you have to specify each member as a property.
It’s also overkill. You’re going to end up sending huge packets of data that are unnecessary. For example if your object has no position, rotation and/or scale data that differs from the default object you’re going to send it anyway every time. And that’s just the basic stuff. There are a LOT of properties in an object, and you don’t need 80% of them most of the time. You’re already fighting against network lag. Don’t spend processor and network time sending that data.
Instead, figure out what is important to send for each object, and only pass those values. You will have less latency and performance problems and you won’t spend time fighting a one-size-fits-all function that’s going to get cumbersome quickly.