Optimizing the bandwidth and avoiding cheating

It can be summarized as follows: the less information a client has, the less opportunity there is of exploiting said information for cheating. Also, the less information a client needs, the less bandwidth is required.

Previously, we've generously sent information about every player, every update cycle. In this recipe, we'll change that so that the server checks what players can be seen by others, and only send that information.

We'll build this on top of the Implementing a network code for FPS recipe.

We need to add some complexity to the simpleUpdate method of the server application. So, instead of sending information about all players to everybody, we need to check who should receive what.

How to do it...

Perform the following steps to optimize a bandwidth:

  1. First of all, we'll add a visible field to our PlayerUpdateMessage. This is so that a client knows when a player has disappeared from the view.
  2. On the server side, we need to change two classes. First, our ServerPlayerControl needs to maintain a list of player IDs it currently sees.
  3. Before we do our checks, we need to make sure all the players are updated:
    Collection<NetworkedPlayerControl> players = game.getPlayers().values();
      for(NetworkedPlayerControl p: players){
        p.update(tpf);
      }
  4. Next, we iterate through our playerMap object. Here, we add a simple range check to see whether a player is visible or not, and lastly broadcast the information to the relevant players, as follows:
    Iterator<HostedConnection> it = playerMap.keySet().iterator();
    while(it.hasNext()){
      HostedConnection conn = it.next();
      ServerPlayerControl player = playerMap.get(conn);
      for(NetworkedPlayerControl otherPlayer: players){
        float distance = player.getSpatial().getWorldTranslation().distance(otherPlayer.getSpatial().getWorldTranslation());
      PlayerUpdateMessage updateMessage = null;
      if(distance < 50){
        updateMessage = createUpdateMessage(otherPlayer);
        player.addVisiblePlayer(otherPlayer.getId());
      } else if (player.removeVisiblePlayer(otherPlayer.getId())){
        updateMessage = createUpdateMessage(otherPlayer);
        updateMessage.setVisible(false);
      }
      if(updateMessage != null){
        server.broadcast(Filters.in(conn), updateMessage);
      }
    }
  5. That's all for the server side. On the client side, we need to add a visible field to ClientPlayerControl.
  6. The second change we make is in ClientMessageHandler. We check whether the player is supposed to be visible, and whether it's attached to the scene graph or not:
    if(p.isVisible() && p.getSpatial().getParent() == null){
      gameClient.getRootNode().attachChild(p.getSpatial());
    } else if (!p.isVisible() && p.getSpatial().getParent() != null){
      gameClient.getRootNode().detachChild(p.getSpatial());
    }

How it works...

By using this principle, each client will only receive updates on other relevant players. We can't, however, just stop sending updates about certain players without also letting the client know why, or they would just freeze in their last known position. That's why the last message the server sends about a player is with visible set to false. However, to do so, the server must keep track of when a player has disappeared, and not just when it's not visible. That's why each ServerPlayerControl class needs to keep track of which players it saw the last update in its visibleList.

This recipe focused on the networking aspects of visibility and how and when to send updates. A proper game (at least an FPS) will need to keep track of obscured players as well, not only how far away they are.

Optimization can be done in different ways, and it all comes down to the application. An MMO may for example not be as dependent on frequent updates. In a game like that, network updates can be done with less frequency, if a player is further away, and instead rely on good interpolation to avoid jerkiness.

If we're using interpolation, and not absolute updates, we should also turn off interpolation when visible switches from false to true, to avoid players possibly gliding to the new position. We can also turn off updates when visible is false.

See also

  • The Sensing – vision recipe in Chapter 5, Artificial Intelligence, which provides an idea on how to implement sight on the server
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.59.198