-
Notifications
You must be signed in to change notification settings - Fork 14
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
Added diff states (no binary serialization, no static typing) - includes fix for the first-state problem. #278
base: main
Are you sure you want to change the base?
Conversation
…piler hits error if function doesnt exist, so typos are caught with static RPC functions)
@@ -4,6 +4,7 @@ class_name PropertyEntry | |||
var _path: String | |||
var node: Node | |||
var property: String | |||
var type: Variant.Type ##see typeof() |
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.
This isn't needed for this PR, but its good to have for any future edits. Freely remove these 2 lines.
get: | ||
return ProjectSettings.get_setting("netfox/rollback/enable_state_diffs", true) | ||
set(v): | ||
enable_state_diffs = v |
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.
Is the setter needless? I am not familiar with Godot's setters/getters.
Also are project settings' values cached on runtime, or does it search project settings' values each time I get()?
## This is often needless for inputs, because in most games, inputs are different (movement + aim/mouse position) | ||
## Set to true if you have many input properties which are not updated often. | ||
## Set to false if your input properties are few and often update (see forest-brawl example, being movement and mouse position) | ||
#@export var enable_input_diffs: bool = false |
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.
I was about to add input diffs as well, but I don't want this PR to get so big that it won't get reviewed (e.g. much time to test, or risky), feel free to remove.
for picked_property in properties_to_include: | ||
diff_state_to_broadcast[picked_property] = full_state_to_broadcast[picked_property] | ||
|
||
#print("At tick %s sent diff state which is: %s " % [tick, diff_state_to_broadcast]) |
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.
Leaving this print line for the sake of testing. Freely remove before merging.
continue | ||
|
||
sanitized[property] = value | ||
for picked_tick in inputs: |
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.
I changed the logic of inputs because they were added [property][tick]
instead of [tick][property]
This change is easier to read (see _after_tick
) and more performant.
Again, if you want, I can remove this. Or move to a seperate PR. I only had it here because I planned to make input diffs as well, and that would require inputs to work with the same format as all other rollback dictionaries, which is [tick][properties]
instead of the current [properties][tick]
…RED) regardless of full or diff. The server always starts by sending full states. Once the client receives any (full) state, he sends an ack to the server to start sending diffs.
All states are sent
UNRELIABLE_ORDERED
regardless if they are a full state (contains all properties) or a diff state (contains only the properties with new values)Once the client receives any state, he sends a
RELIABLE
rpc to the server that he has indeed received a full state, and so it can start receiving diff states. Once thisRELIABLE
rpc is received by the server, all future states sent to that specific peer are diff states, instead of full states. Diff states are states whose property/values included are only those which have changed from the previous tick.This implementation also solves the diff states problem mentioned in #264 (this is the 2nd way, and I think its the cleanest and most performant)
I have tested it and found no issues.
Solves #157
As for the bandwidth it saves, see forest-brawl example: "Displaceable:mass", "Displaceable:impulse", ":speed" which change only once via powerup, so 3/5 states are skipped with diff states. Assuming the variables were of same size, with diff states, there is 60% less bandwidth.
Requires #277 which is just static typing additions (so this PR is easy to read, instead of having double the size)