This class contains information about a backend server
        public async void ServerPacketReceived(PacketReceivedEventArgs e)
        {
            var packet = e.Packet as DisconnectPacket;
            if (packet != null)
            {
                Exception exception = null;
                try
                {
                    Match result = endPointRegex.Match(packet.Reason);

                    if (result.Success)
                    {
                        e.Handled = true;
                        int version = 0;
                        if (result.Groups["version"].Success)
                            version = int.Parse(result.Groups["version"].Value);
                        var info = new RemoteServerInfo(result.ToString (),
                                                        new IPEndPoint(await FindAddress(result.Groups["ip"].Value),
                                                                       result.Groups["port"].Success
                                                                           ? int.Parse(result.Groups["port"].Value)
                                                                           : 25565), version);

                        IProxyConnection connection = e.Connection;

                        Packet pa = await connection.InitializeServerAsync(info);

                        if (pa is DisconnectPacket)
                        {
                            await e.Connection.ClientEndPoint.SendPacketAsync(pa);
                            return;
                        }
                        var logonResponse = pa as LogOnResponse;
                        //Add entity id mapping
                        Plugin.EntityIDMapping.AddOrUpdate(e.Connection,
                                                           new Tuple<int, int>(e.Connection.EntityID,
                                                                               logonResponse.EntityId), (a, b) => b);

                        var state = new InvalidState {Reason = 2}; // Stop raining
                        await connection.ClientEndPoint.SendPacketAsync(state);

                        var respawn = new Respawn
                                          {
                                              World = logonResponse.Dimension == 0 ? -1 : 0,
                                              //Force chunk and entity unload on client
                                              CreativeMode = (byte) logonResponse.ServerMode,
                                              Difficulty = logonResponse.Difficulty,
                                              Generator = logonResponse.Generator, //for compatibility
                                              MapSeed = logonResponse.MapSeed, //for compatibility
                                              WorldHeight = (short) logonResponse.WorldHeight
                                          };
                        await connection.ClientEndPoint.SendPacketAsync(respawn);
                        //now send the correct world
                        respawn.World = logonResponse.Dimension;
                        await connection.ClientEndPoint.SendPacketAsync(respawn);
                        await Task.Delay(500); // I don't like this too :(
                        connection.StartServerListening ();

                        Plugin.Logger.InfoFormat("{0} got transferred to {1}", e.Connection.Username, info.EndPoint);
                        return;
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error(ex);
                    exception = ex;
                }
                if (exception != null)
                    await e.Connection.KickUserAsync(exception.Message);
            }

            ApplyServerEntityIDFixes(e);
        }
        /// <summary>
        ///   Get the minecraft protocol server of a given minecraft server.
        /// </summary>
        /// <param name="proxyConnection"> The connection this server relates to. </param>
        /// <param name="serverEndPoint"> The current version of the Remote server info. </param>
        public void GetServerVersion(IProxyConnection proxyConnection, RemoteServerInfo serverEndPoint)
        {
            var args = new PluginResultEventArgs<RemoteServerInfo>(serverEndPoint, proxyConnection);

            PluginManager.TriggerPlugin.GetServerVersion(args);

            args.EnsureSuccess ();

            if (serverEndPoint.MinecraftVersion == 0)
            {
                //Look up configuration

                ProxyConfigurationSection settings = ProxyConfigurationSection.Settings;

                IEnumerable<ServerElement> serverList =
                    settings.Server.OfType<ServerElement> ().Where(
                        m => m.EndPoint == serverEndPoint.EndPoint.ToString ());

                ServerElement server = serverList.FirstOrDefault ();

                if (server != null) serverEndPoint.MinecraftVersion = server.MinecraftVersion;
                    //Use default
                else serverEndPoint.MinecraftVersion = ProtocolInformation.MaxSupportedServerVersion;
            }
        }