-
-
Notifications
You must be signed in to change notification settings - Fork 57
refactor: Server pattern #549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Great stuff!! |
| # Resolve to identifier | ||
| var identifier := NetworkIdentityServer.resolve_reference(peer, idref) | ||
| if not identifier: | ||
| # TODO: Handle unknown IDs gracefully |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow-up PR
| if buffer == null: | ||
| buffer = StreamPeerBuffer.new() | ||
|
|
||
| # TODO: How about encoding the first snapshot as-is, and then the rest as diffs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow-up PR
| # Resolve to identifier | ||
| var identifier := NetworkIdentityServer.resolve_reference(peer, idref) | ||
| if not identifier: | ||
| # TODO: Handle unknown IDs gracefully |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow-up PR
| func record_state(tick: int) -> void: | ||
| var input_snapshot := get_rollback_input_snapshot(tick - 1) | ||
| _record(tick, _rb_state_snapshots, _rb_state_properties, false, func(subject: Node): | ||
| if not subject.is_multiplayer_authority(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Server always has authority to broadcast states
| if not subject.is_multiplayer_authority(): | |
| if subject.multiplayer.is_server(): | |
| return true | |
| if not subject.is_multiplayer_authority(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might have to investigate why is_predicting() was returning true in this case. Otherwise we risk overwriting a client's prediction with ticks that the server had no input for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without the suggested change, RollbackSimulationServer.is_predicting() would return true for the other player's car on the server, because of this clause:
if is_owned and not has_input:
# We own the node, node depends on input, we don't have data for input - predict
return trueSo as long as we haven't received input from the client, we consider the recorded simulation predicted, which - in theory - makes sense. I guess next thing to find out is why we need to forego the above.
On clients, is_predicting() returns false for the player's car with this clause:
if not is_owned and has_input:
# We don't own the node, but we own input for it - not (input) predicting
return false| NetworkHistoryServer.restore_rollback_input(tick) | ||
| NetworkHistoryServer.restore_rollback_state(tick) | ||
| on_prepare_tick.emit(tick) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signals first
| NetworkHistoryServer.restore_rollback_input(tick) | |
| NetworkHistoryServer.restore_rollback_state(tick) | |
| on_prepare_tick.emit(tick) | |
| on_prepare_tick.emit(tick) | |
| NetworkHistoryServer.restore_rollback_input(tick) | |
| NetworkHistoryServer.restore_rollback_state(tick) |
| RollbackSimulationServer.simulate(NetworkTime.ticktime, tick) | ||
| on_process_tick.emit(tick) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| RollbackSimulationServer.simulate(NetworkTime.ticktime, tick) | |
| on_process_tick.emit(tick) | |
| on_process_tick.emit(tick) | |
| RollbackSimulationServer.simulate(NetworkTime.ticktime, tick) |
| NetworkHistoryServer.record_state(tick + 1) | ||
| NetworkSynchronizationServer.synchronize_state(tick + 1) | ||
| on_record_tick.emit(tick + 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| NetworkHistoryServer.record_state(tick + 1) | |
| NetworkSynchronizationServer.synchronize_state(tick + 1) | |
| on_record_tick.emit(tick + 1) | |
| on_record_tick.emit(tick + 1) | |
| NetworkHistoryServer.record_state(tick + 1) | |
| NetworkSynchronizationServer.synchronize_state(tick + 1) |
| NetworkHistoryServer.restore_rollback_state(display_tick) | ||
| RollbackSimulationServer.trim_ticks_simulated(history_start) | ||
| after_loop.emit() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| NetworkHistoryServer.restore_rollback_state(display_tick) | |
| RollbackSimulationServer.trim_ticks_simulated(history_start) | |
| after_loop.emit() | |
| after_loop.emit() | |
| NetworkHistoryServer.restore_rollback_state(display_tick) | |
| RollbackSimulationServer.trim_ticks_simulated(history_start) | |
| "name": "NetworkSynchronizationServer", | ||
| "path": ROOT + "/servers/rollback-synchronization-server.gd" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File change fix
| "name": "NetworkSynchronizationServer", | |
| "path": ROOT + "/servers/rollback-synchronization-server.gd" | |
| "name": "NetworkSynchronizationServer", | |
| "path": ROOT + "/servers/network-synchronization-server.gd" |
| NetworkHistoryServer.restore_synchronizer_state(tick) | ||
| before_tick_loop.emit() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
signals before rs's
| NetworkHistoryServer.restore_synchronizer_state(tick) | |
| before_tick_loop.emit() | |
| before_tick_loop.emit() | |
| NetworkHistoryServer.restore_synchronizer_state(tick) |
| NetworkHistoryServer.record_sync_state(tick + 1) | ||
| NetworkSynchronizationServer.synchronize_sync_state(tick + 1) | ||
| after_tick.emit(ticktime, tick) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too
| NetworkHistoryServer.record_sync_state(tick + 1) | |
| NetworkSynchronizationServer.synchronize_sync_state(tick + 1) | |
| after_tick.emit(ticktime, tick) | |
| after_tick.emit(ticktime, tick) | |
| NetworkHistoryServer.record_sync_state(tick + 1) | |
| NetworkSynchronizationServer.synchronize_sync_state(tick + 1) |
| NetworkHistoryServer.restore_synchronizer_state(tick) | ||
| after_tick_loop.emit() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| NetworkHistoryServer.restore_synchronizer_state(tick) | |
| after_tick_loop.emit() | |
| after_tick_loop.emit() | |
| NetworkHistoryServer.restore_synchronizer_state(tick) |
This is an experimental PR, that refactors much of netfox's internals, inspired by Godot's server pattern.
While Godot had its own requirements, the interpretation here is that:
Hopefully this allows:
Also lays the foundations for some potentially wild features like:
TODO:
Pending fixes:
Sanity tasks: