As part of RPCs processing, they need to be sorted reliably across all
peers, so that unique IDs can be assigned to greatly optimize the
network layer.
The RPC configuration nodes are stored in dictionaries which, until
recently, always casted StringName keys to String.
Since method names (keys) in the RPC configuration were StringName,
a side effect of the above change is that sorting the dictionary keys no
longer sort them alphabetically by default (StringName are compared
using their pointers).
This commit changes the RPC processing logic to use sort_custom to
provide a function that can handle the StringName comparison.
The debugger reports synchronizers with empty state to the editor
even if no data is being sent to other peers.
The editor conditional to avoid division by zero was checking the wrong
variable.
- Instead of checking for Key::UP, Key::DOWN, Key::PAGEUP, Key::PAGEDOWN etc., we rather check for the action like 'ui_up' or 'ui_down'.
- Also use AcceptDialog's 'register_text_enter' functionality to consistently close a dialog when ENTER is pressed while the LineEdit has focus (instead of redirecting ENTER keys to e.g. the underlying Tree).
- Unify the LineEdit filter behavior for the SceneTreeDialog and corresponding usages
- Improve OK Button disablement (something should be selected)
Godot supports sending messages to "all but one peer" by sending a
packet with a negative target (the negated ID of the excluded peer).
The relay protocol was incorrectly interpreting the values and relaying
the message to the wrong peers.
This issue only affected "send_bytes" since the other subsystem (RPC
and replication) "resolves" the correct IDs client-side (to match
visibility information).
When multiple clients are connected, and the server is using the relay
sub-protocol, it might happen that a client disconnects while a packet
sent to it from another peer is still in transit.
In that case, when the packet reaches the server for relaying, it used
to generate an error (as the destination client did no longer exists).
This commit changes check to suppress the error message while still
skipping the packet.
Cleaning up remote NodePath cache is not trivial since the visibility
API allows for certain nodes to be despawned (and re-spawned) on some
peers while being retained in the authority.
This means that from the server point of view, the node has not changed,
and the path simplification protocol won't be run again after
respawning.
While we can track this information for synchronizers via the
replication API, we can't easily track this information for potential
child nodes that use RPCs (I'm convinced it is doable, but we need to
track the whole dependency tree which would require some more complex
refactoring).
This commit partially reverts some of the cache cleanup logic to always
retain remote IDs, and adds a NodePath lookup fallback when the ObjectID
is invalid.
Random-access access to `List` when iterating is `O(n^2)` (`O(n)` when
accessing a single element)
* Removed subscript operator, in favor of a more explicit `get`
* Added conversion from `Iterator` to `ConstIterator`
* Remade existing operations into other solutions when applicable
It's possible that after sending a cached node reference (e.g. RPC or
static MultiplayerSynchronizer) the reference node is removed from tree
before the remote peer(s) can confirm the referenced path.
To better detect that case, and avoid spamming errors when it happens,
this commit modifies the multiplayer API caching protocol, to send the
received ID instead of the Node path when sending the confirmation
packet.
**This is a breaking change** because it makes the runtime multiplayer
protocol incompatible with previous versions of Godot.
Default shortcuts use the first or second letter of each word.
This also adds a new shortcut to toggle the last opened bottom panel.
On editor startup, this defaults to the first panel in the list
(which is the Output panel).
This change introduces a new EditorThemeManager class
to abstract theme generatio and its subroutines.
Logic related to EditorTheme, EditorColorMap, and editor
icons has been extracted into their respective files with
includes cleaned up.
All related files have been moved to a separate folder to
better scope them in the project. This includes relevant
generated files as well.
The auth implementation was treating any received packet as a remote
confirmation after the peer was confirmed locally.
It now correctly awaits for the remote confirmation packet before
admitting new peers.
Synchronizers for spawned nodes were not correctly keeping track of the
net ID assigned by the remote, preventing the replication from
performing the proper cleanup.
This resulted in errors being thrown when sync messages were received
after despawn (which is possible due to their unreliable nature).
Ensures that spawnable nodes (i.e. spawned nodes over which the local
instance has authority) always have a network ID, since they may lose it
after the multiplayer is reset (e.g. when changing the multiplayer peer).
The SceneMultiplayer complete_auth method was not configuring the
multiplayer peer correctly, causing it to potentially send the
notification to the wrong peer, on the wrong channel, and/or with an
incorrect transfer mode.
Fix set_multiplayer_authority not resetting the synchronizer.
Fix the reset function not clearing the watchers state.
Skip wrap around check for the first sync packet after reset.
This allows to include script_instance.h directly in the
generated gdvirtual.gen.inc, and remove excessive includes
from the codebase.
This should also allow Resource to use GDVIRTUAL macros,
which wasn't possible previously due to a circular dependency.
REPLICATION_MODE_ALWAYS (sync) and REPLICATION_MODE_ON_CHANGE (watch)
are now mutually exclusive.
Prevent invalid NodePath from being added to the config.
Optimize the replication config loading by composing the lists on
demand.
Allows synchronizing (sub-)resource properties, transform components,
etc. by using subnames.
As an example, `.:transform.x` will only synchronize the `x` component
of the root transform instead of the whole transform.
This can also be used to synchronize a resource own properties, as long
as they are synchronizable (i.e. the property itself is not an Object,
RID, or Callable).
We don't use that info for anything, and it generates unnecessary diffs
every time we bump the minor version (and CI failures if we forget to
sync some files from opt-in modules (mono, text_server_fb).