-
-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
MultiplayerSynchronizer get_cached_object miss returning ERR_UNAUTHORIZED on server relay #58193
Comments
Interestingly, this only happens when there is more than one client connected to the server, so my guess is a bug in the way path-only sync (i.e. synchronizers with a root object that was not spawned directly) are exchanged. Will need some further investigation, but confirmed. |
I've found another slightly different use case that seems to do the same thing, and is the smallest example I can think of. Here we've got a node that is part of the default scene in the game, so it's loaded on clients by default (no MultiplayerSpawner spawning it across the network!). Replication steps: Errors should start piling up on both client instances. |
I tried looking into this a little further.
If I'm understanding correctly, for path-only nodes the net_id will get populated when we first sync to the first client - so we won't call send_object_cache for subsequent clients.
I don't fully have my head around the net_id stuff. My first instinct was to replace the However, it does raise a warning (
Am I heading in the right direction? |
… network authority, per discussion with Faless. Note: This relies on a custom Godot build, due to path-only sync bug with Alpha 2 (godotengine/godot#58193)
@MitchMakesThings thanks a lot for looking into this! diff --git a/scene/multiplayer/scene_replication_interface.cpp b/scene/multiplayer/scene_replication_interface.cpp
index 25a704b37e..0764f136e4 100644
--- a/scene/multiplayer/scene_replication_interface.cpp
+++ b/scene/multiplayer/scene_replication_interface.cpp
@@ -350,11 +350,12 @@ void SceneReplicationInterface::_send_sync(int p_peer, uint64_t p_msec) {
}
if (size) {
uint32_t net_id = rep_state->get_net_id(oid);
- if (net_id == 0) {
+ if (net_id == 0 || (net_id & 0x80000000)) {
// First time path based ID.
NodePath rel_path = multiplayer->get_root_path().rel_path_to(sync->get_path());
int path_id = 0;
multiplayer->send_object_cache(sync, rel_path, p_peer, path_id);
+ ERR_CONTINUE_MSG(net_id && net_id != (uint32_t(path_id) | 0x80000000), "This should never happen!");
net_id = path_id;
rep_state->set_net_id(oid, net_id | 0x80000000);
} |
Man, I definitely need to brush up on my C++! Doesn't that mean at the bottom of the if statement, when we call Wouldn't we need to know whether it's been cached for that particular Is the idea of |
What the |
Ah, that's the bit I was missing! Thanks for the explanation! I've tested your change against the two example projects in this thread, and it seems to be working perfectly :) |
Godot version
Godot Engine v4.0.alpha2.official.79077e6c1
System information
Windows 10, Vulkan API 1.2.0
Issue description
Using the new MultiplayerSynchronizer node throws errors when clients have authority, and a server is relaying from one client to another. This isn't an issue when the server has authority over MultiplayerSynchronizer.
On clients, I get:
E 0:00:13:0487 get_cached_object: ID 2 not found in cache of peer 1719405227. <C++ Error> Condition "!F" is true. Returning: nullptr <C++ Source> scene/multiplayer/scene_cache_interface.cpp:235 @ get_cached_object()
E 0:00:13:0487 on_sync_receive: Condition "!sync || sync->get_multiplayer_authority() != p_from" is true. Returning: ERR_UNAUTHORIZED <C++ Source> scene/multiplayer/scene_replication_interface.cpp:381 @ on_sync_receive()
The latter is caused by the former returning a nullptr. I started looking into the cached object stuff, but I'm not really familiar with the Godot codebase.
Unrelated, but the server also logs an error when closing one of the clients:
E 0:00:30:0819 _relay: Condition "!peers.has(p_to)" is true. <C++ Source> modules/enet/enet_multiplayer_peer.cpp:601 @ _relay()
There might not be anything different to do here - client A has asked the server to relay a message to client B, but B has disconnected. Logging and forgetting about the message seems sensible.
Steps to reproduce
Use the multiplayer demo project @Faless uploaded on #55950
Minimal reproduction project
multiplayer_bomber_spawn_node.zip
The text was updated successfully, but these errors were encountered: