google search for: https://www.google.com/search?client=firefox-b-d&q=socket+io+game+server+architecture
n/a
quick overview of a co-op jigsaw puzzle game
- a central server for "high level tasks" e.g. player connection
- specific controllers for a game and a player
- each higher-level thing emits events which are consumed by relevant bodies
3 types of data:
- immutable, persistent state, temporary state
Good overview of server/client interaction:
These are all the steps in chronological order:
1. The game view reacts on the key down event sent by the browser and sends a “move right” event to the client controller.
2. The client controller checks if the character can move based on the current snapshot of the game state. For example, if there is a wall which blocks the way, it could discard the event. If the action is possible, the client controller updates the temporary position of the character and redraws the game view. It also sends a “move right” event to the server using a web socket.
3. The player controller on the server receives a “move right” event through the web socket. It passes the event to the game controller along with the information about the player whose character is to be moved.
4. The game controller checks if the given player’s character can move to the right. Based on that information, it might accept or reject the action. If the action is possible, the game controller updates the persistent state of the game and sends the “state changed” event to all player controllers associated with the game.
5. The player controllers serialize the data that has changed and send it to the clients using their corresponding web sockets.
6. The client controllers that are currently connected to the game receive the “state changed” event with the new data. They update the persistent state of the game and redraw the view if necessary.
https://medium.com/bluecadet/just-enough-multiplayer-a-simple-start-for-prototyping-realtime-multi-user-spaces-with-socket-io-1fd260ef3e54
context: a really simple example of keeping track of central state, receiving updates from players and broadcasting central state
- many issues arise from handling latency, though how you handle it depends on actual game
- render main player separately
Frontend code = https://github.com/ChrisArasin/simple-multiplayer-client Serverside code = https://glitch.com/~simple-multiplayer-server
context: video series on using socketio and express. Watched up until ep3
- each socket connection has and id, which you can store
- what data do you send to server? What is required to keep everything in sync, while also verifying the data?
- they chose to send an update only when there is a change to the local state (i.e. new keypresses) and then the server handles everything
context: a long series about networked physics. Very into the weeds on technical optimizations of sending/receiving physics data
Some techniques of [[extrapolation & interpolation of game state]].
Deterministic lockstep = only send inputs from each client
- least bandwidth usage
- deterministic physics models are rare and so they get out of sync frmo small differences in clients and [[floating point determinism]]
- requires [[playout delay buffer]] aka "buffering", because you need all inputs to appear as if they're arriving at a consistent pace even though network speed/delivery is inconsistent
- you wait a little and then "play" data once you have enough to render it properly (e.g. waiting 200ms for a bunch of frames)
- you send the frame order so other clients can order them properly
- you can UDP, but send ALL of your inputs (encoded), instead of an ordered stream
- doesn't scale well with multiple players because you have to wait for the slowest player
Snapshot Interpolation
- lots of bandwidth
- send full states and have client approximate transitions from one to another (e.g. linear interpretation)
- some rules-of-thumb for doing this and achieving a balance of visuals, accuracy and network reliance
- requires delay to create a "snapshot window" that you interpolate with
- how many packets can you lose? What is baseline network latency?
- compress snapshots, optimize data sent for linear velocity (which helps keep interpolation accurate), optimize position accuracy, use [[delta encoding]] and other [[bit-packing techniques]]
State Synchronization
- combination of physics input and state
- balanced approach which extrapolates from last state with last inputs, updating to new states once they are received (big differences result in a visual "pop" as objects are corrected)
- you can "smooth" your approach back to the new state so you don't "pop" as much (e.g. slowly reduce the error isntead of instantly)
context: an article series about fast-paced multiplayer games
it's all about cheating, physics and lag
a purely 'dumb' client that sends data to server and only updates when it receives response
- baseline lag between input and action
So! You use [[client prediction]] and [[server reconciliation]] to give the "illusion of responsiveness"
Use a [[server time step]] to make updates predictable, but this can be choppy. Use [[extrapolation & interpolation of game state]]
- biggest factor is [[predictability of game entities]] and how they're used in the game itself
- dead reckoning = show the future state as if it was continuing exactly from its last received state. Not good if object can change a lot.
- entity interpolation = use a delay and interpolate between 2 positions from the past. Not good if real-time visuals are needed (e.g. aiming)
- the solution to this is calculating the state on the server with [[lag compensation]]
Client/Server trust
- use [[server time step]] + [[extrapolation & interpolation of game state]] to balance valid game states with smooth client experience
- these depend on [[predictability of game entities]]
- server should always validate inputs from client e.g. a player should be bound to certain speeds and positions
- client should always send and ask the server if sometthing is OK, then wait for a response
- send minimum data possible. Run same checks on user commands locally for speed then on server for control.
- local vs remote physics = if things need to be in-sync and they depend on physics, they should be done in server, otherwise things will get out of sync
Data management
- immutable, persistent state, temporary state
- what data do you send to server? What is required to keep everything in sync, while also verifying the data?
- they chose to send an update only when there is a change to the local state (i.e. new keypresses) and then the server handles everything
- you can send metadata along with state to help smooth things over (e.g. timestamp from clients/servers to help properly order things)
Clustering
- manage various groups of users across multiple servers (e.g. [[games are managed through rooms in ioHelper]])
- [[load balancing]] of your servers
- [[cluster (node)]] package
Sockets
- keep track of different socket connections in order to send relevant information in a scoped way (i.e. [[socket server rooms]]
- global
- voice chat
- specific games that users have joined
- each time there is a connection, the socket has a unique ID that you can track
- keep all of one user's IDs stored so you can make sure to send them the right data & track across windows/tabs
Persistance
- fast read/write to redis
- sync with some DB for starting/restarting and failures
Handling latency EventEmitters & Class controller hierachies
Read these:
- https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/
- https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization
Look at these:
- Frontend code = https://github.com/ChrisArasin/simple-multiplayer-client
- Serverside code = https://glitch.com/~simple-multiplayer-server