public function onData($data)
    {
        //if we're in encryption stage decrypt it first
        if($this->secret !== null) {
            mcrypt_generic_init($this->encryptor, $this->secret, $this->secret);
            $data = mdecrypt_generic($this->encryptor, $data);
            mcrypt_generic_deinit($this->encryptor);
        }

        //attempt to parse the data as a packet
        try {

            //add the data to the current buffer
            $this->packetBuffer .= $data;

            //for as long as we have data left in the buffer
            do {

                //read the packet length from the stream
                $packetLengthVarInt = VarInt::readUnsignedVarInt($this->packetBuffer);

                //not enough data to read the packet length, wait for more data
                if($packetLengthVarInt === false) {
                    return;
                }

                //total length of the packet is the length of the varint + it's value
                $totalLength = $packetLengthVarInt->getDataLength() + $packetLengthVarInt->getValue();

                //if we don't have enough data to read the entire packet wait for more data to enter
                $bufferLength = strlen($this->packetBuffer);
                if ($bufferLength < $totalLength) {
                    return;
                }

                //remove the packet length varint from the buffer
                $this->packetBuffer = substr($this->packetBuffer, $packetLengthVarInt->getDataLength());

                //read the packet ID from the buffer
                $packetDataWithPacketID = substr($this->packetBuffer, 0, $packetLengthVarInt->getValue());

                //remove the rest of the packet from the buffer
                $this->packetBuffer = substr($this->packetBuffer, $packetLengthVarInt->getValue());

                //read the packet ID
                $packetID = VarInt::readUnsignedVarInt($packetDataWithPacketID);

                //get the raw packet data
                $packetData = substr($packetDataWithPacketID, $packetID->getDataLength());

                $this->lastPacket = $this->currentTime();

                //trigger packet processing
                $this->processPacket($packetID->getValue(), $packetData);

                //if we have buffer left run again
            } while (strlen($this->packetBuffer) > 0);

            //if any exceptions are thrown (error parsing the packets e.t.c.) send a disconnect packet
        } catch (Exception $ex) {
            echo "EXCEPTION IN PACKET PARSING {$ex->getMessage()}\n";
            echo $ex->getTraceAsString();
            $dis = new DisconnectPacket();
            $dis->setReason('Internal Server Error: '.$ex->getMessage());
            $this->end($dis->encodePacket());
        }
    }