docs: function(client, packet) {
              var eaters_count = packet.readUInt16LE();
  
              client.tick_counter++;
  
              //reading eat events
              for(var i=0;i<eaters_count;i++) {
                  var eater_id = packet.readUInt32LE();
                  var eaten_id = packet.readUInt32LE();
  
                  if(client.debug >= 4)
                      client.log(eater_id + ' ate ' + eaten_id + ' (' + client.balls[eater_id] + '>' + client.balls[eaten_id] + ')');
  
                  if(!client.balls[eater_id]) new Ball(client, eater_id);
                  client.balls[eater_id].update();
                  if(client.balls[eaten_id]) client.balls[eaten_id].destroy({'reason':'eaten', 'by':eater_id});
  
                  client.emitEvent('somebodyAteSomething', eater_id, eaten_id);
              }
  
              //reading actions of balls
              while(1) {
                  var is_virus = false;
                  var ball_id;
                  var coordinate_x;
                  var coordinate_y;
                  var size;
                  var color;
                  var nick = null;
  
                  ball_id = packet.readUInt32LE();
                  if(ball_id == 0) break;
                  coordinate_x = packet.readSInt32LE();
                  coordinate_y = packet.readSInt32LE();
                  size = packet.readSInt16LE();
  
                  var color_R = packet.readUInt8();
                  var color_G = packet.readUInt8();
                  var color_B = packet.readUInt8();
  
                  color = (color_R << 16 | color_G << 8 | color_B).toString(16);
                  color = '#' + ('000000' + color).substr(-6);
  
                  var opt = packet.readUInt8();
                  is_virus = !!(opt & 1);
                  var something_1 = !!(opt & 16); //TODO what is this?
  
                  //reserved for future use?
                  if (opt & 2) {
                      packet.offset += packet.readUInt32LE();
                  }
                  if (opt & 4) {
                      var something_2 = ''; //TODO something related to premium skins
                      while(1) {
                          var char = packet.readUInt8();
                          if(char == 0) break;
                          if(!something_2) something_2 = '';
                          something_2 += String.fromCharCode(char);
                      }
                  }
  
                  while(1) {
                      char = packet.readUInt16LE();
                      if(char == 0) break;
                      if(!nick) nick = '';
                      nick += String.fromCharCode(char);
                  }
  
                  var ball = client.balls[ball_id] || new Ball(client, ball_id);
                  ball.color = color;
                  ball.virus = is_virus;
                  ball.setCords(coordinate_x, coordinate_y);
                  ball.setSize(size);
                  if(nick) ball.setName(nick);
                  ball.update_tick = client.tick_counter;
                  ball.appear();
                  ball.update();
  
                  if(client.debug >= 5)
                      client.log('action: ball_id=' + ball_id + ' coordinate_x=' + coordinate_x + ' coordinate_y=' + coordinate_y + ' size=' + size + ' is_virus=' + is_virus + ' nick=' + nick);
  
                  client.emitEvent('ballAction', ball_id, coordinate_x, coordinate_y, size, is_virus, nick);
              }
  
              var balls_on_screen_count = packet.readUInt32LE();
  
              //disappear events
              for (i=0;i<balls_on_screen_count;i++) {
                  ball_id = packet.readUInt32LE();
  
                  ball = client.balls[ball_id] || new Ball(client, ball_id);
                  if (ball.mine) {
                      ball.destroy({reason: 'merge'});
                      client.emitEvent('merge', ball.id);
                  } else {
                      ball.disappear();
                      ball.update_tick = client.tick_counter;
                      ball.update();
                  }
              }
          }