TheTrackerCouncil / SMZ3Randomizer

Tracker presents: a casual standalone version of the Super Metroid & A Link to the Past Crossover Randomizer with built-in automatic item tracking and Twitch integration
https://vivelin.net/projects/smz3
MIT License
26 stars 9 forks source link

Multiworld Server #237

Closed MattEqualsCoder closed 1 year ago

MattEqualsCoder commented 2 years ago

My current thoughts for the flow is as follows. Some of the class names are definitely just whatever came to mind, so they could be updated.

Creating a new game

  1. Put in basic details about the game such as type (currently only multiworld) and the server details
  2. Connect to server via a port
  3. Send a CreateGameRequest with the above details and get a CreateGameResponse with game guid and some sort of basic connection string to give to other people to connect until we have the lobby system up in a future release.

Joining a game

  1. The player will enter the connection string from above
  2. The player will enter in all of their personal config options such as item locations, logic, sprite ,etc.
  3. Connect to the server via port
  4. Send a JoinGameRequest with the game guid, and your configs, and get a JoinGameResponse that will send back the player states of all of the other player and a player unique guid.
  5. This will also send to everyone else a PlayerJoinedResponse with the new player's config details
  6. The game info will be stored in a new "MultiplayerGames" table as at this point theoretically the game may not be started and they'll need to rejoin.

Starting a game

  1. The host will have a start game button that will initiate the actual seed generation on their side
  2. Once they are done, generating, they'll send a StartGameRequest to the server with all of the world details for each player. Each player will then get their first GameStateResponse. These will be periodically sent by the server with the details of each player as a sort of sync in case an individual item gets dropped along the way. On receiving your first one, you'll generate the world based on the details.
  3. Once generated, the game will be launchable like normal, though I may have multiplayer games in a separate tab in the main window to separate them out and make it easier to make.

Sending updates

  1. My general thought is that updates will all be handled by sending location cleared states. So you'll send the server "I cleared location X in my world" and since every player has all details from all worlds, they can look up the item at that location in their instance. This will make things consistent between single updates and the syncs that happen.
  2. So, when a player gets a location, they'll send a PlayerStateUpdateRequest that'll be sent out to all of the other players as PlayerStateUpdateResponse which will have the details of which player is sending the info and what location was cleared.
  3. One thing to note is that the cleared status here is not the actual cleared status in the state, but it's the autotracked value as that'll be most reliable.

Forfeiting

  1. When a player forfeits, it'll basically update that player's state to having all locations as cleared, which will be picked up by the players normally. This will be done in a PlayerForfeiitRequest and PlayerForfeitResponse
  2. If the host forfeits, the next player in line will be marked as the new host player.

Rejoining

  1. When a player rejoins, they'll simply get updated with the latest state for all players just like normal. This will allow them to see what the difference is between the local version that they have and the data from the server.

Client Classes

  1. There will be some sort of MultiplayerService which will handle opening the connection and sending/receiving messages.
  2. I'm imagining that there will be some sort of MultiplayerGameMode abstract class or interface. By default we'll only have multiworld implement it, but I'd like to add different ones for co-op and that shuffler idea I mentioned. Each game mode will do the actual creating of the messages to send and will manage the responses differently so that they can function differently.
Vivelin commented 2 years ago

I'd refrain from calling it "connection string", I think that's a little too complicated for most people and for technical people it could be confusing with e.g. DB connection strings.

On joining games: I'd introduce some "Test connection" functionality, so you don't spend all that time configuring things if it turns out to be wrong/not up or something.

I think maybe SignalR or something similar might be a decent idea while the game is running.

MattEqualsCoder commented 2 years ago

Yeah, I was thinking of framing it more like a URL for users. Mostly just meant some details might be parsed out like a connection string.

Good call on the SignalR. Wasn't aware of its existence. Looks pretty nifty.

This coming week I'll probably start experimenting with getting some sort of setup in my Linux VM and make sure I can setup a back and forth connection.