Skip to content
This repository has been archived by the owner on Jan 28, 2021. It is now read-only.

Turn based (Asynchronous) multiplayer support #610

Open
krist00fer opened this issue Dec 18, 2017 · 4 comments
Open

Turn based (Asynchronous) multiplayer support #610

krist00fer opened this issue Dec 18, 2017 · 4 comments

Comments

@krist00fer
Copy link
Contributor

Think chess. Like what is the backend services/functions you would need to implement a multiplayer chess game, where one player makes a move and pass it on to another player through some kind of service. We don't need to implement server side game engine implementation to start with, but rather a set of services/functions to pass "game state" from one player to another.

Example how it could be implemented

  • Game state is encoded in any way the client likes. Perhaps JSON but other will also work.
  • Clients can send state to a SessionId. The SessionId identifies the multiplayer session, most often returned by the match making service.
  • Every time a new game state is submitted the session state will have a new and updated StateId. The StateId is returned everytime game state is submitted.
  • Clients can pull latest StateId for a specific SessionId. This allow the clients to "pull" for changes. If any change has occurred, then the StateId will not be the same as the last knows StateId.
  • As soon as a client figure out the state has changed it can pull/get the last state.
  • It's then going to be up to the clients and the encoded state to contain information about things like: what does the state mean, who is next to make a move, etc.

Please comment with your ideas

@dgkanatsios
Copy link
Collaborator

Some random/general comments from my side (since I've been brainstorming about such a mechanism, too)

  • Instead of asynchronous, maybe call it turn based?
  • Game server should be authoritative, in the sense that state is kept on the server and can be fetched by the clients as desired. You describe exactly the same thing in mentioning clients can pull latest StateId
  • Game server also would not let cheating, i.e. player with white pieces move two pieces on their turn. This would require the server to have an internal state machine (a simple C# enum, probably)
  • Mechanism to be used for message exchange would be either plain HTTP polling or something more advanced like WebSockets (SignalR or Socket.io?). We could always go to the TCP/UDP path but I think this will require more complexity than an HTTP/JSON solution
  • Since game is asynchronous (not real-time) we could have an external state store for the server. For example, server(s) could host game data in a Redis Cache, rather than in memory

Comments on your points

  • As soon as a client figure out the state has changed it can pull/get the last state. <- Or have the server push down the latest message/state change
  • I'm not 100% sure if we indeed need a stateId. This might be needed for game history purposes (this would be great in chess - how a game was played) but I think that the only necessary thing for the server to push is the last change (i.e. queen move from X to Y)

@krist00fer krist00fer changed the title Asynchronous multiplayer support Turn based (Asynchronous) multiplayer support Dec 19, 2017
@krist00fer
Copy link
Contributor Author

@dgkanatsios I agree with you on the name, let's call it "Turn based" to make everyone understand. Good idea!

@krist00fer
Copy link
Contributor Author

@dgkanatsios many of your other ideas also make sense. Some of them have been processed by my brain before me writing this issue at all, but thanks for challenging me. That's what this is all about, us working together. I'll try to answer your comments one after another here:

  • Authoritative game server isn't always a must have. You would be amazed how many games out there that doesn't have authoritative servers... and some of them surely should. But still many games don't and have decided not to do so by a reason. And one reason might be simplicity or lower server cost. If we can make an example on how to plugin game server logic we should, but I don't think we should defer a Pull Request of a "turn based scenario" just because it doesn't have that feature. Also running the game simulation on the server side to be fully authoritative requires information about the actual game play in order to be implementable. But I agree with you, in a perfect world, game servers shouldn't be hackable.
  • Message exchange should ideally be implemented using a communication protocol that allows "push" messages from the server. As of right now (with the new "serverless approach") Nether is built on a "base architecture" that uses Azure Functions. As far as I know, we don't yet have the ability to use any protocol that allow you to push from the server to the client using Azure Functions. Please correct me if I'm out of date here. With that said, we don't need to rely on Azure Functions only. If we want to implement a "turn based server scenario" and want to go outside of the "base architecture" then we can surely do so, we just need to take special care that we make it as easy to use as the other scenarios (or at least simple enough). Also, at the same time we should support the super simple base architecture as much as we can and if we can have a turn based server that uses polling from the clients implemented using Azure Functions, that would be valuable as well. So SignalR, Socket.io, TCP/UDP doesn't work with Azure Functions. So once again, I agree with that statement and you
  • The standard "base architecture" deployes an Azure Function Account and a Cosmos DB Account. If doable, we should try and use that architecture first. If it doesn't work or doesn't full fill what we want to achieve we could add more resources like Redis. But I agree, we could/should use external storage for state and that could perhaps be CosmosDB
  • With regards to what the state contains, like you mentioned: "instead of sending the full state, just send what has changed", my initial thoughts was to have the developer decide that. As a developer I just pass some state from one client to another, if that state is my full "chess board" or only the "changes of my chess board" then that is up to me to chose and understand what to do with.

Thanks a lot for your feedback. @dgkanatsios is this something you want to give a try?

@dgkanatsios
Copy link
Collaborator

  • regarding authoritative game servers, I think that the backend should have at least some logic behind it. Take out cheating and imagine a tic-tac-toe game. You absolutely want
    a) the same player should make only one move and then wait for the other player
    b) winner should be determined
    c) X or O cannot be placed more than once on each tic-tac-toe 'cell'
    This might complicate the server a bit, but I guess that these rules could be rewritten as a simple rule engine (XML? JSON?) which could be read by both server and client.
  • while I can think of Azure Functions responding to HTTP web requests that contain player's movement and then do some polling to check for the next player's move, I agree with you that a push mechanism is the ideal scenario. However, this totally disqualifies Functions, since with their limited life (5 to 10 minutes max) they cannot be used for this kind of workload.
  • I'm already working on a "push" implementation for a simple chat scenario. I'm using socket.io (a WebSocket implementation) + a Unity client I found, I'm tracking all work here https://github.com/dgkanatsios/AzureGameChat (still WIP). I'll post again once I have something more concrete.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants