diff --git a/addons/netfox.extras/physics/physics_driver.gd b/addons/netfox.extras/physics/physics_driver.gd index c7991d3e..8ddb0d02 100644 --- a/addons/netfox.extras/physics/physics_driver.gd +++ b/addons/netfox.extras/physics/physics_driver.gd @@ -8,6 +8,8 @@ class_name PhysicsDriver var physics_space: RID var snapshots: Dictionary = {} +var _known_bodies: Dictionary = {} + # Number of physics steps to take per network tick @export var physics_factor: int = 2 # Snapshot and Rollback entire physics space. @@ -21,6 +23,7 @@ func _enter_tree(): #rollback ticks if rollback_physics_space: NetworkRollback.on_prepare_tick.connect(on_prepare_tick) + NetworkRollback.before_loop.connect(_update_space_floor) NetworkRollback.on_process_tick.connect(on_process_tick) func _exit_tree(): @@ -30,6 +33,7 @@ func _exit_tree(): #rollback ticks if NetworkRollback.on_prepare_tick.is_connected(on_prepare_tick): NetworkRollback.on_prepare_tick.disconnect(on_prepare_tick) + NetworkRollback.before_loop.disconnect(_update_space_floor) NetworkRollback.on_process_tick.disconnect(on_process_tick) func _ready() -> void: @@ -37,7 +41,9 @@ func _ready() -> void: # Emitted before a tick is run. func before_tick(delta: float, tick: int) -> void: - _snapshot_space(tick) + if rollback_physics_space: + _update_space_floor() + _snapshot_space(tick) step_physics(delta, tick) func on_prepare_tick(tick: int) -> void: @@ -72,6 +78,13 @@ func step_physics(delta: float, tick: int) -> void: func _init_physics_space() -> void: pass +func _update_space_floor() -> void: + for body: Node in get_tree().get_nodes_in_group("network_rigid_body"): + if _known_bodies.has(body): + continue + _known_bodies[body] = true + NetworkRollback.notify_resim_floor(NetworkTime.tick) + ## Override this method to take one step in the physics space. ## [br][br] ## It should also flush and update all Godot nodes diff --git a/addons/netfox/network-time.gd b/addons/netfox/network-time.gd index 6f5a7df6..2a60f0ca 100644 --- a/addons/netfox/network-time.gd +++ b/addons/netfox/network-time.gd @@ -565,6 +565,7 @@ func _loop() -> void: if ticks_in_loop > 0: _before_tick_loop() + var first_tick := _tick for i in ticks_in_loop: before_tick.emit(ticktime, tick) on_tick.emit(ticktime, tick) @@ -580,7 +581,7 @@ func _loop() -> void: _tick += 1 _next_tick_time += ticktime - _after_tick_loop() + _after_tick_loop(first_tick) # Send queued network identities NetworkIdentityServer.flush_queue() @@ -605,9 +606,9 @@ func _before_tick_loop() -> void: InterpolationServer._apply_target_state() before_tick_loop.emit() -func _after_tick_loop() -> void: +func _after_tick_loop(first_tick: int = -1) -> void: # Run rollback loop - NetworkRollback._rollback() + NetworkRollback._rollback(first_tick) # Emit signal after_tick_loop.emit() diff --git a/addons/netfox/rollback/network-rollback.gd b/addons/netfox/rollback/network-rollback.gd index a97c2908..f90069b2 100644 --- a/addons/netfox/rollback/network-rollback.gd +++ b/addons/netfox/rollback/network-rollback.gd @@ -164,6 +164,8 @@ var _rollback_from: int = -1 var _rollback_to: int = -1 var _rollback_stage: String = "" +var _resim_floor: int = -1 + # Resim + mutations var _is_rollback: bool = false var _simulated_nodes: _Set = _Set.new() @@ -186,6 +188,9 @@ static var _logger: NetfoxLogger = NetfoxLogger._for_netfox("NetworkRollback") func notify_resimulation_start(p_tick: int) -> void: _resim_from = min(_resim_from, p_tick) +func notify_resim_floor(p_tick: int) -> void: + _resim_floor = maxi(_resim_floor, p_tick) + ## Submit node for simulation. ## ## This is used mostly internally by [RollbackSynchronizer]. The idea is to @@ -354,7 +359,7 @@ func _get_rollback_tag() -> String: else: return "_" -func _rollback() -> void: +func _rollback(frame_from_tick: int = -1) -> void: if not enabled: return @@ -364,6 +369,9 @@ func _rollback() -> void: # Figure out where to start rollback from var range_source = "notif" + if frame_from_tick >= 0 and frame_from_tick <= _resim_from: + range_source = "frame start" + _resim_from = frame_from_tick if _earliest_input >= 0 and _earliest_input <= _resim_from: range_source = "earliest input" _resim_from = _earliest_input @@ -371,6 +379,9 @@ func _rollback() -> void: range_source = "latest state" _resim_from = _earliest_state _resim_from = mini(_resim_from, NetworkTime.tick - 1) + if _resim_floor >= 0 and _resim_from < _resim_floor: + _resim_from = _resim_floor + range_source = "resim floor" _logger.trace("Simulating range @%d>@%d using %s", [_resim_from, NetworkTime.tick, range_source]) # Only set _is_rollback *after* emitting before_loop