// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/protocol/AbstractSqlPacket.java
// public abstract class AbstractSqlPacket {
// 
//     public abstract ProtocolId getProtocol();
// 
//     protected abstract void write(ByteArrayDataOutput to);
// 
//     protected abstract void read(ByteArrayDataInput from);
// 
//     @SneakyThrows
//     public byte[] encode() {
//         ByteArrayDataOutput buf = ByteStreams.newDataOutput();
//         buf.writeByte(getProtocol().ordinal());
//         write(buf);
//         return buf.toByteArray();
//     }
// 
//     public static AbstractSqlPacket decode(byte[] input) {
//         ByteArrayDataInput buf = ByteStreams.newDataInput(input);
//         ProtocolId protocolId = ProtocolId.values()[buf.readByte()];
//         AbstractSqlPacket packet = ProtocolId.ofPacket(protocolId);
//         packet.read(buf);
//         return packet;
//     }
// }
// 
// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/protocol/DataRequest.java
// @Data
// @EqualsAndHashCode(callSuper = false)
// public class DataRequest extends AbstractSqlPacket {
// 
//     private UUID id;
// 
//     @Override
//     public ProtocolId getProtocol() {
//         return ProtocolId.REQUEST;
//     }
// 
//     @Override
//     protected void write(ByteArrayDataOutput buf) {
//         buf.writeLong(id.getMostSignificantBits());
//         buf.writeLong(id.getLeastSignificantBits());
//     }
// 
//     @Override
//     protected void read(ByteArrayDataInput from) {
//         id = new UUID(from.readLong(), from.readLong());
//     }
// }
// 
// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/protocol/DataSupply.java
// @Data
// @EqualsAndHashCode(callSuper = false)
// public class DataSupply extends AbstractSqlPacket {
// 
//     private UUID id;
//     private String group;
//     private byte[] buf;
// 
//     @Override
//     public ProtocolId getProtocol() {
//         return ProtocolId.CONTENTS;
//     }
// 
//     @Override
//     protected void write(ByteArrayDataOutput out) {
//         out.writeLong(id.getMostSignificantBits());
//         out.writeLong(id.getLeastSignificantBits());
//         out.writeUTF(group);
//         out.writeInt(buf.length);
//         out.write(buf);
//     }
// 
//     @Override
//     protected void read(ByteArrayDataInput from) {
//         id = new UUID(from.readLong(), from.readLong());
//         group = from.readUTF();
//         buf = new byte[from.readInt()];
//         from.readFully(buf);
//     }
// }
// 
// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/protocol/ProtocolId.java
// public enum ProtocolId {
// 
//     READY,
//     CONTENTS,
//     REQUEST;
// 
//     @NotNull
//     public static AbstractSqlPacket ofPacket(@NotNull ProtocolId id) {
//         switch (id) {
//             case READY:
//                 return new PeerReady();
//             case CONTENTS:
//                 return new DataSupply();
//             case REQUEST:
//                 return new DataRequest();
//         }
//         throw new EnumConstantNotPresentException(ProtocolId.class, "Unknown " + id);
//     }
// }


import com.github.caoli5288.playersql.bungee.protocol.AbstractSqlPacket;
import com.github.caoli5288.playersql.bungee.protocol.DataRequest;
import com.github.caoli5288.playersql.bungee.protocol.DataSupply;
import com.github.caoli5288.playersql.bungee.protocol.ProtocolId;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.event.ServerConnectedEvent;
import net.md_5.bungee.api.event.ServerKickEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.function.BiConsumer;
        }
    }

    private void peerReady(ProxiedPlayer player, AbstractSqlPacket packet) {
        if (Constants.DEBUG) {
            getLogger().info("PEER_READY id=" + player.getUniqueId());
        }
        states.put(player.getUniqueId(), new ConnectState());
    }

    @EventHandler
    public void handle(PluginMessageEvent event) {
        if (!event.getTag().equals(Constants.PLUGIN_CHANNEL)) {
            return;
        }
        AbstractSqlPacket packet = AbstractSqlPacket.decode(event.getData());
        handlers.get(packet.getProtocol()).accept((ProxiedPlayer) event.getReceiver(), packet);
    }

    @EventHandler(priority = Byte.MAX_VALUE)
    public void handle(ServerConnectEvent event) {
        UserConnection conn = (UserConnection) event.getPlayer();
        UUID id = conn.getUniqueId();
        ConnectState state = states.get(id);
        if (state == null) {
            return;
        }
        if (state.getContents() == null) {// check contents null to compatible with some balancer
            state.setConnect(event.getTarget());
            event.setCancelled(true);
// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/protocol/AbstractSqlPacket.java
// public abstract class AbstractSqlPacket {
// 
//     public abstract ProtocolId getProtocol();
// 
//     protected abstract void write(ByteArrayDataOutput to);
// 
//     protected abstract void read(ByteArrayDataInput from);
// 
//     @SneakyThrows
//     public byte[] encode() {
//         ByteArrayDataOutput buf = ByteStreams.newDataOutput();
//         buf.writeByte(getProtocol().ordinal());
//         write(buf);
//         return buf.toByteArray();
//     }
// 
//     public static AbstractSqlPacket decode(byte[] input) {
//         ByteArrayDataInput buf = ByteStreams.newDataInput(input);
//         ProtocolId protocolId = ProtocolId.values()[buf.readByte()];
//         AbstractSqlPacket packet = ProtocolId.ofPacket(protocolId);
//         packet.read(buf);
//         return packet;
//     }
// }
// 
// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/protocol/DataRequest.java
// @Data
// @EqualsAndHashCode(callSuper = false)
// public class DataRequest extends AbstractSqlPacket {
// 
//     private UUID id;
// 
//     @Override
//     public ProtocolId getProtocol() {
//         return ProtocolId.REQUEST;
//     }
// 
//     @Override
//     protected void write(ByteArrayDataOutput buf) {
//         buf.writeLong(id.getMostSignificantBits());
//         buf.writeLong(id.getLeastSignificantBits());
//     }
// 
//     @Override
//     protected void read(ByteArrayDataInput from) {
//         id = new UUID(from.readLong(), from.readLong());
//     }
// }
// 
// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/protocol/DataSupply.java
// @Data
// @EqualsAndHashCode(callSuper = false)
// public class DataSupply extends AbstractSqlPacket {
// 
//     private UUID id;
//     private String group;
//     private byte[] buf;
// 
//     @Override
//     public ProtocolId getProtocol() {
//         return ProtocolId.CONTENTS;
//     }
// 
//     @Override
//     protected void write(ByteArrayDataOutput out) {
//         out.writeLong(id.getMostSignificantBits());
//         out.writeLong(id.getLeastSignificantBits());
//         out.writeUTF(group);
//         out.writeInt(buf.length);
//         out.write(buf);
//     }
// 
//     @Override
//     protected void read(ByteArrayDataInput from) {
//         id = new UUID(from.readLong(), from.readLong());
//         group = from.readUTF();
//         buf = new byte[from.readInt()];
//         from.readFully(buf);
//     }
// }
// 
// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/protocol/ProtocolId.java
// public enum ProtocolId {
// 
//     READY,
//     CONTENTS,
//     REQUEST;
// 
//     @NotNull
//     public static AbstractSqlPacket ofPacket(@NotNull ProtocolId id) {
//         switch (id) {
//             case READY:
//                 return new PeerReady();
//             case CONTENTS:
//                 return new DataSupply();
//             case REQUEST:
//                 return new DataRequest();
//         }
//         throw new EnumConstantNotPresentException(ProtocolId.class, "Unknown " + id);
//     }
// }


// Path: bungee/src/main/java/com/github/caoli5288/playersql/bungee/PlayerSqlBungee.java
import com.github.caoli5288.playersql.bungee.protocol.AbstractSqlPacket;
import com.github.caoli5288.playersql.bungee.protocol.DataRequest;
import com.github.caoli5288.playersql.bungee.protocol.DataSupply;
import com.github.caoli5288.playersql.bungee.protocol.ProtocolId;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.event.ServerConnectedEvent;
import net.md_5.bungee.api.event.ServerKickEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.function.BiConsumer;

        }
    }

    private void peerReady(ProxiedPlayer player, AbstractSqlPacket packet) {
        if (Constants.DEBUG) {
            getLogger().info("PEER_READY id=" + player.getUniqueId());
        }
        states.put(player.getUniqueId(), new ConnectState());
    }

    @EventHandler
    public void handle(PluginMessageEvent event) {
        if (!event.getTag().equals(Constants.PLUGIN_CHANNEL)) {
            return;
        }
        AbstractSqlPacket packet = AbstractSqlPacket.decode(event.getData());
        handlers.get(packet.getProtocol()).accept((ProxiedPlayer) event.getReceiver(), packet);
    }

    @EventHandler(priority = Byte.MAX_VALUE)
    public void handle(ServerConnectEvent event) {
        UserConnection conn = (UserConnection) event.getPlayer();
        UUID id = conn.getUniqueId();
        ConnectState state = states.get(id);
        if (state == null) {
            return;
        }
        if (state.getContents() == null) {// check contents null to compatible with some balancer
            state.setConnect(event.getTarget());
            event.setCancelled(true);
            DataRequest request = new DataRequest();