Friday 20 September 2013

The Minecraft main game loop

Minecraft uses two main game loops, one for the client and one for the server.
The client loop is primarily responsible for reading input from the player and for rendering the screen.
The server loop is responsible for maintaining the master copy of the world - updating the blocks and entities based on packets received from the client, and sending updated information to all the clients. 
Communication between the server and the clients is done using Packets.  Some information here, more to follow when I figure it out myself.

Client Game Loop

The key concepts for the Client Game Loop are:
  • The activities in the game loop are broadly grouped into (1) clock-based (Ticks) and (2) variable-timing (mostly - display rendering).  
  • The game loop calls the clock-based update code (.runTick) twenty times per second.  If the loop gets behind (for example due to slow rendering or other programs), it will repeatedly call .runTick until it catches up to real time.
  • In contrast, the display rendering is not time-critical.  Rendering is performed only when the Ticks are up-to-date.  If the game loop slows down, the framerate will be reduced but the Ticks will remain in synchronisation.
  • Actions which affect the world / entities are sent to the server for processing.
  • The state of client objects (blocks, entities, etc) is updated in response to packets received from the server.
  •  It can be very useful to insert breakpoints at key locations in .runTick(), in order to diagnose problems with player actions or entity AI.
  • Likewise, troubleshooting many rendering problems can be achieved by putting breakpoints in the appropriate parts of EntityRenderer.renderWorld.

Server Game Loop

Unlike the client loop, the server loop is essentially all clock-based (Ticks).  Key concepts:
  • The server is responsible for performing Block Ticks (both scheduled and random) and Entity Ticks (eg movement, AI, etc).
  • The server receives packets from the clients whenever the client performs an action which might affect the world or other entities.  It processes the packet to updates the world and entity states as appropriate, then sends the updated information to all relevant clients.
  • Sometimes the same code runs independently on both the client and the server (for example - blocklight and skylight calculation).  This reduces the amount of information that needs to be sent between client and server - there's no need to send information that can be locally calculated, so long as the client and server remain synchronised.