diff --git a/addons/netfox/servers/network-synchronization-server.gd b/addons/netfox/servers/network-synchronization-server.gd index 430b2ac9..745ee5cb 100644 --- a/addons/netfox/servers/network-synchronization-server.gd +++ b/addons/netfox/servers/network-synchronization-server.gd @@ -36,6 +36,8 @@ var _rb_enable_input_broadcast := ProjectSettings.get_setting("netfox/rollback/e var _rb_enable_diffs := NetworkRollback.enable_diff_states var _rb_full_interval := ProjectSettings.get_setting("netfox/rollback/full_state_interval", 24) as int var _rb_full_scheduler := _IntervalScheduler.new(_rb_full_interval) +var _rb_last_synced_tick := -1 +var _rb_last_synced_snapshot: _Snapshot = null var _input_redundancy := NetworkRollback.input_redundancy @@ -138,6 +140,9 @@ func deregister(node: Node) -> void: _sync_owned_state_properties.erase_subject(node) _visibility_filters.erase(node) _schemas.erase_subject(node) + + if _rb_last_synced_snapshot: + _rb_last_synced_snapshot.erase_subject(node) func _is_node_visible_to(peer: int, node: Node) -> bool: var filter := _visibility_filters.get(node) as PeerVisibilityFilter @@ -203,14 +208,22 @@ func _synchronize_state(tick: int) -> void: if snapshot.is_empty(): # Nothing to send return + + # Resimulated ticks at or below _rb_last_synced_tick were already sent + # Peers resimulate from the newest received state so don't send them again + if tick <= _rb_last_synced_tick: + return + _rb_last_synced_tick = tick # Figure out whether to send full- or diff state var is_full := _rb_full_scheduler.is_now() if not _rb_enable_diffs: is_full = true - # Check if we have history to diff to - var reference_snapshot := NetworkHistoryServer._get_rollback_state_snapshot(tick - 1) + # Diff against the state as it was last sent (last authoritative state) + # Mirrors _last_sync_state_sent in _synchronize_sync_state() + # Duplicated because rollback history snapshots are mutated during resim + var reference_snapshot := _rb_last_synced_snapshot if not reference_snapshot: is_full = true @@ -228,7 +241,7 @@ func _synchronize_state(tick: int) -> void: else: var diff := _Snapshot.make_patch(reference_snapshot, snapshot) if diff.is_empty(): - # Nothing changed, don't send anything + # Nothing changed, don't send anything, and don't update _rb_last_synced_snapshot return # Send diff states @@ -241,6 +254,9 @@ func _synchronize_state(tick: int) -> void: NetworkPerformance.push_full_state_props(snapshot.size()) NetworkPerformance.push_sent_state_props(diff.size()) + + # Update the cached snapshot for future rollbacks + _rb_last_synced_snapshot = snapshot.duplicate() func _synchronize_sync_state(tick: int) -> void: # We don't own sync state, nothing to synchronize @@ -298,6 +314,13 @@ func _init( _simulation_server = p_simulation_server func _ready(): + # NetworkTime.tick restarts every session, so reset the "last_synced" data + NetworkTime.after_sync.connect(func(): + _rb_last_synced_tick = NetworkTime.tick - 1 + _rb_last_synced_snapshot = null + ) + + # Ensure dependencies if not _command_server: _command_server = NetworkCommandServer if not _history_server: _history_server = NetworkHistoryServer