-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
rewrite multiplayer spawner and synchronizer, making it a module #62870
Conversation
cbca790
to
b035d01
Compare
3221182
to
ae4674a
Compare
I did take a look at #62320, but I don't think it'll be resolved here. I'll give it a test though! (Also thanks for taking a look 😃) (Note GH actions, I have fixed them locally but I am also doing other fixes) |
734a35a
to
45ae023
Compare
Well, that took quite a while! I believe I got #62320 resolved, and I also got spawner subchildren working. Explanation:Previously, when a client joined, the server would receive the peer_connected signal and each Spawner would send the client the nodes that were needed. However, since signals are not called in a deterministic order, it was possible for the player spawner to send its RPC before the World spawner even created it. Solution: Now, the server doesn't listen to peer_connected, but rather the client requests the spawns/syncs when the spawner is initialized. This also prevents errors if for whatever reason the Spawner/Synchronizer exists on the server but not the client. This also paves the way for proposals such as godotengine/godot-proposals#3904, since the server no longer expects all clients to have the same Spawners and Synchronizers. (Lots of work is still needed, however, as there is nothing preventing a client from pretending to have those nodes) Edit: Also updated OP with a testing project |
I wish you had written a proposal, or contacted me about this, I've been doing work on interest management that will collide with this PR. |
45ae023
to
6cd59ee
Compare
Also in general, using |
To expand on this, I really appreciate your work in trying to implement those features, and I like the idea of clients requesting spawns, which is something likely needed, but there are some issues with the way this has been rewritten:
I am currently finishing my work on the interest management proposal, which should also solve some of the issues, I would be happy to discuss further changes on top of that if needed. Again, I really appreciate you working on this, and I think there are good ideas, but it cannot be accepted as is, and I would advise against putting more work on this before I finish the work on interest management proposal, because that should solve most of the issues already, and would certainly conflict with this. This came at an unfortunate timing, I am sorry about it :/ . |
Attempting some trials: Specification:
In my case, since Godot 4 doesn't yet have headless, I couldn't use my normal server, so instead I used my laptop at home. It was connected to ProtonVPN in Japan to simulate a relatively poor connection with high latency.
The fundamental problem with too many nodes:
Layman's terms:
I also had some issues where the peer would time out in the 1000 nodes trial. I am assuming this is from too many packets. I think a great improvement would be bundling the data into a single packet
Hmm. I don't see what is particularly important about abstracting the replication interface. I'd imagine the biggest use case for multiplayer modules would be another multiplayer peer type (e.g. a Steamworks module that makes RPCs go through steam). Even if someone wants to modify the replication interface, they could disable the module and write their own (or copy some code).
I agree with both! How about, following your work with interest management and approval, I move all the functionality (e.g. networked spawning/syncing) to a singleton, which manages the spawners/syncs and bundles requests together? |
6cd59ee
to
565efe6
Compare
565efe6
to
5ebf7af
Compare
I just want to give my opinion in that, I believe every piece of code that can be made abstract/extendable should be, as that is one of the ultimate reasons why I enjoy Godot as an engine in the first place, and should hopefully remain so into the future. Generality is slower then specialization, but can often support specialization while still being generic. |
See #63049 ❤️ |
Fixes #62027
Fixes #61711
Fixes #62320
Testing project: test7.zip
Tests:
CC @Faless
Note for reviewers:
replication_editor_plugin.*
andscene_replication_config.*
are not modified, except for#ifdef TOOLS_ENABLED
and some imports.multiplayer_spawner.*
andmultiplayer_synchronizer.*
have changed considerably.Note the use of RPCs. It isn't going to be perfectly space efficient, but the majority of the data being sent is
Variant
s (which are encoded the same way regardless) so it's not a big deal. Only other issue is the methods are technically exposed to GDScript, allowing the user to override them. I worked around it by naming the methods, but there should be a better solution. See #32585._internal_rpc_
...Edit: I am only naming them
_rpc_
because thinking again, private methods should be inaccessible (un-overridable?) by default.Edit 2: Just noting here for future reference. I do respect the way the previous spawner/synchronizer handles packets, it is more versatile for bare C++. However, given the current multiplayer system, I don't think it's possible for a module (or gdextension) to make a custom packet. If this is desired though, rather than moving it to core, it would be better to implement a way for any module/gdextension to make its own packets.