extends _BaseSnapshotSerializer class_name _SparseSnapshotSerializer static func _static_init(): _logger = NetfoxLogger._for_netfox("SparseSnapshotSerializer") func write_for(peer: int, snapshot: _Snapshot, properties: _PropertyPool, filter: Callable = _default_filter, buffer: StreamPeerBuffer = null) -> PackedByteArray: if buffer == null: buffer = StreamPeerBuffer.new() var netref := NetworkSchemas._netref() var varuint := NetworkSchemas.varuint() var varbits := NetworkSchemas._varbits() var node_buffer := StreamPeerBuffer.new() var has_data := false # Write ticks buffer.put_u32(snapshot.tick) # For each node for subject in properties.get_subjects(): if not filter.call(subject): continue if not snapshot.is_auth(subject): continue var node := subject as Node assert(node.is_multiplayer_authority(), "Trying to serialize state for non-owned node!") assert(snapshot.is_auth(node), "Trying to serialize non-auth state node!") # Write identifier if _write_identifier(node, peer, buffer) != OK: continue node_buffer.clear() var node_props := properties.get_properties_of(node) var changed_bits := _Bitset.new(node_props.size()) for i in node_props.size(): var property := node_props[i] if not snapshot.has_property(node, property): continue changed_bits.set_bit(i) var value := snapshot.get_property(node, property) _write_property(node, property, value, node_buffer) varuint.encode(node_buffer.data_array.size(), buffer) # Node props len varbits.encode(changed_bits, buffer) # Changed prop bits buffer.put_data(node_buffer.data_array) # Changed props has_data = true if has_data: return buffer.data_array else: # Return an empty buffer if we ended up not serializing anything return PackedByteArray() func read_from(peer: int, properties: _PropertyPool, buffer: StreamPeerBuffer, is_auth: bool = true) -> _Snapshot: var netref := NetworkSchemas._netref() var varuint := NetworkSchemas.varuint() var varbits := NetworkSchemas._varbits() var node_buffer := StreamPeerBuffer.new() # Grab ticks var tick := buffer.get_u32() var snapshot := _Snapshot.new(tick) while buffer.get_available_bytes() > 0: # Read header, including identity reference var idref := netref.decode(buffer) as _NetworkIdentityReference var node_data_size := varuint.decode(buffer) as int var changed_bits := varbits.decode(buffer) as _Bitset node_buffer.data_array = buffer.get_partial_data(node_data_size)[1] # Resolve to identifier var identifier := _get_identity_server()._resolve_reference(peer, idref) if not identifier: # TODO(#563): Handle unknown IDs gracefully _logger.warning("Received unknown identity reference %s, skipping data", [idref]) break var node := identifier.get_subject() as Node # Read changed properties var node_props := properties.get_properties_of(node) for idx in changed_bits.get_set_indices(): var property := node_props[idx] var value := _read_property(node, property, node_buffer) snapshot.set_property(node, property, value) snapshot.set_auth(node, is_auth) return snapshot