Emulator Issues #13204open
[Feature request] Netplay drop-in (host savestate syncing)
I could've sworn this was put into the issue tracker before, but I did a search and couldn't find anything.
It would be neat if Dolphin's netplay had support for drop-in, where players can join a game mid-session. Currently, Dolphin doesn't allow users to join games as soon as they are started. This is a bit of an inconvenience since there might be instances where a player might want to join a game already in progress due to in-game progression or potential connection instability. This would help in games like Gauntlet Dark Legacy, where games can go on for a long time without an opportunity for saving. By having support for drop-in, a player can just connect to the game and drop right in without the host having to shut the server down.
This might have been a bit unfeasible a decade or so ago, but since internet connections with decent upload speeds are more common than what they were back then, drop-in should be doable for most users these days.
The way drop-in should work should be similar to this:
1.) The host should have the ability to disable/enable drop-in. This will prevent bad users from constantly connecting and disconnecting, causing intentional interruptions in-game. Ideally, it would also be great if the setting itself could be enabled or disabled by the host even as the game is running, so the host can prevent interruptions during critical moments during a netplay session.
2.) When a client wants to connect to the host, it might be best to allow connections through automatically. It might be possible to do an in-window allow/deny for incoming connections without having to pause the gameplay for all clients, but in the meantime, if the host allows drop-in, just allow the user in automatically.
3.) When the client is granted a connection to the host, Dolphin sends the hash of the disc image that the host is currently using to the client. If it matches, proceed. If it doesn't, deny and warn the user that the sums do not match. This will ensure that the game the client connects with is exactly the same as the hosts. I'm not sure if Dolphin always calculates the hash value of the disc image before every session. It might be best to do so and store the sums in RAM, this way the host can just send the hashes to clients who want to connect, so only the clients themselves have to calculate the hashes. This will prevent performance issues on the host's end if there's an active session.
4.) With the disc image confirmed, load up the game on the client's end and transfer the following from the host:
- The host's memory card or saved game files.
- A compressed savestate containing the host's current frame.
- Any additional forced configurations that are forced by the host onto the clients.
- Connected peripherals, like GBAs. In the case of GBA's, savestate information should also be generated for each GBA window by the host and transferred as well.
5.) On the host's and connected clients' end, the game will pause and alert all connected players of an incoming connection in a window. The window should print the incoming user name and a progress bar detailing the transfer (progress and rate) and connection status.
6.) Once the connecting client has connected, if the player count exceeds 4 players, treat them as a spectator. If the current player count is less than or equal to 4 players, put the connecting client on the next available controller port and treat this controller as connected for all players.
7.) Finally, once the savestate and memory card files have been restored on their end, resume the game. All the clients should now be in sync.
One thing I was thinking, in order to speed up the transfer of the saved state, is to use the peer-to-peer transfer of the savestate file. Although, I believe that regardless of how much each client is in sync, there will always be some level of variance in the emulated state from peer to peer (like the contents of RAM). In order for peer-to-peer to work, you'd have to ensure that every user's savestate that gets created matches exactly the same. This might be unfeasible given how much potential there is for a variance from client to client. Maybe it might be possible to do differential transfers (kinda like rsync) where bytes that are the same from each client transfer over, but bytes that differ transfer from the host instead of the clients. I don't know how feasible this would be in practice, however, so it's just a thought.
I also wonder if instead of sending the savestate/memory card data to just the client who wants to connect if this might be an opportunity to have the host send that data to every connected client as well. This will enforce that all clients that connect are on the same exact page on the host. But again, per-client variance might not allow this to be preferred.
Savestate and memory card/save file compression is definitely critical in this scenario. An appropriate compression algorithm must be used to ensure that not only the save data and memory card files are compressed as small as possible, but restoring from the transferred data can occur on the client as fast as possible.
No data to display