fpclass / perpetual-haskelling-initiative

Main repository for the CS141 Perpetual Haskelling Initiative
MIT License
0 stars 0 forks source link

Server #8

Open dixonary opened 4 years ago

dixonary commented 4 years ago

If the game is to be played online, there will need to be a server component which takes moves from the clients and translates that into changes in game state (which are then propagated back to the client).

Dealing with multiple ongoing games is a stretch goal!

mbg commented 4 years ago

See #5 for some existing comments regarding this!

oscar-h64 commented 4 years ago

So its probably time to start having a look at the network element, there's a few different ways I can think of (though my knowledge of networks isn't amazing so I almost certainly will get something wrong):

Server/Client:

Platform Agnostice P2P

Discord/Slack Bot

Plus whatever else I've missed

mbg commented 4 years ago

I think the best way to go about this is to implement the game mechanics independently of whatever communications method is used. We can then add those on top as needed (incl. multiple).

dixonary commented 4 years ago

One problem with P2P is that if clients get out of sync then things can start to go wrong. If there is an authoritative server, then it can communicate the game state to all clients.

As far as I know the clients would have to keep checking the API for updates

With websockets, you can avoid the need to poll the server - the server can push updates to the game state.

A downside of websockets is that you need to manually deal with disconnecting / reconnecting clients though, so a RESTful approach (with HTTP, and server polling) might be simpler. Making an HTTP request for updates every second or so wouldn't be too demanding.

A slack/discord bot would be simple but I'm not sure how that would integrate with a UI?

dixonary commented 4 years ago

In terms of a simple protocol, something like this would be sufficient:

/makeMove - a POST request to tell the server that the client has made a move. Details of the move encoded in JSON body, for example. When the server receives this it should validate the move to check it makes sense in context, and perform the state transformation if yes. /getState - a GET request which returns the current state of the game (encoded as a JSON body) if it's changed since the last request, otherwise it returns HTTP202 or similar.

Plus some metagame stuff like /connect to connect to the game, if there's space.

Making that API support >1 game at a time can be a stretch goal.

Thoughts?

oscar-h64 commented 4 years ago

Yeah a RESTful API with servant was my preferred choice. I'll open a PR for that later this evening. The server will obviously validate the input syntactically okay, although I thing making sure its logically okay is more likely to be a library function than in the server module

oscar-h64 commented 4 years ago
Endpoints: Endpoint Method Description
/connect POST This attempts to connect the user to a game. It must be passed the users deck and it will return a gameID and a player number which is used in future requests
/gameReady/#gameID GET This returns a Bool of whether the game is ready or not - ie whether the 2nd player has joined yet
/state/#gameID/#player?update=#time GET This returns the Board of the current game. If there has been no change since the time stated in the update parameter then HTTP304: Not Modified is returned
/state/#gameID/#player PATCH This takes the [Card] representing the cards the player wishes to play and attempts to play it. If the cards are not valid then HTTP400: Bad Request is returned
oscar-h64 commented 4 years ago

So the single game server has been merged, the next step is supporting multiple concurrent games. There's a couple of ways to implement this:

I don't know much about efficiency, using a Data.Map to store the game states may be more efficient then reading from a DB constantly as with the DB it has to read the data from a string to the data type, however I don't know how well Data.Map would handle large numbers of elements. (Again I want to make it very clear this is very uninformed speculation)

Thoughts?

oscar-h64 commented 4 years ago

I'm going the try using a database, if it turns out to be horrible I'll use STM