// Path: src/main/java/net/techcable/spudcompat/protocol/PlayerConnection.java
// public interface PlayerConnection {
// 
//     public default boolean isSupportedVersion() {
//         return ProtocolVersion.getById(getVersionId()) != null;
//     }
// 
//     public default ProtocolVersion getVersion() {
//         int id = getVersionId();
//         ProtocolVersion version = ProtocolVersion.getById(id);
//         if (version != null) {
//             return version;
//         } else {
//             throw new IllegalStateException("Unsupported version: " + id);
//         }
//     }
// 
//     public ProtocolState getState();
// 
//     public int getVersionId();
// 
//     public void sendPacket(RawPacket rawPacket);
// 
//     public Channel getChannel();
// 
//     public Server getServer();
// }
// 
// Path: src/main/java/net/techcable/spudcompat/protocol/ProtocolState.java
// @RequiredArgsConstructor
// public enum ProtocolState {
//     HANDSHAKE(Protocol.HANDSHAKE),
//     LOGIN(Protocol.LOGIN),
//     PLAY(Protocol.GAME),
//     STATUS(Protocol.STATUS);
// 
//     private final Protocol bungee;
// 
//     public Protocol toBungee() {
//         return bungee;
//     }
// }


import java.lang.reflect.Field;
import io.netty.channel.Channel;
import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.protocol.MinecraftDecoder;
import net.md_5.bungee.protocol.Protocol;
import net.techcable.spudcompat.protocol.PlayerConnection;
import net.techcable.spudcompat.protocol.ProtocolState;
package net.techcable.spudcompat.protocol.injector;




public abstract class AbstractPlayerConnection implements PlayerConnection {

    @Override
    public void sendPacket(RawPacket rawPacket) {
        getChannelWrapper().write(rawPacket.getAllData());
    }

    @Override
    public Channel getChannel() {
        return getChannelWrapper().getHandle();
    }

    private static final Field minecraftDecoderProtocolField;

    static {
        try {
            minecraftDecoderProtocolField = MinecraftDecoder.class.getDeclaredField("protocol");
            minecraftDecoderProtocolField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            throw new AssertionError("Couldn't find protocol field", e);
        }
    }

    @Override
    public ProtocolState getState() {
        Protocol protocol;
        try {
            protocol = (Protocol) minecraftDecoderProtocolField.get(getChannel().pipeline().get(MinecraftDecoder.class));
        } catch (IllegalAccessException e) {
            throw new AssertionError("Couldn't access protocol field");
        }
        switch (protocol) {
            case GAME:
// Path: src/main/java/net/techcable/spudcompat/protocol/PlayerConnection.java
// public interface PlayerConnection {
// 
//     public default boolean isSupportedVersion() {
//         return ProtocolVersion.getById(getVersionId()) != null;
//     }
// 
//     public default ProtocolVersion getVersion() {
//         int id = getVersionId();
//         ProtocolVersion version = ProtocolVersion.getById(id);
//         if (version != null) {
//             return version;
//         } else {
//             throw new IllegalStateException("Unsupported version: " + id);
//         }
//     }
// 
//     public ProtocolState getState();
// 
//     public int getVersionId();
// 
//     public void sendPacket(RawPacket rawPacket);
// 
//     public Channel getChannel();
// 
//     public Server getServer();
// }
// 
// Path: src/main/java/net/techcable/spudcompat/protocol/ProtocolState.java
// @RequiredArgsConstructor
// public enum ProtocolState {
//     HANDSHAKE(Protocol.HANDSHAKE),
//     LOGIN(Protocol.LOGIN),
//     PLAY(Protocol.GAME),
//     STATUS(Protocol.STATUS);
// 
//     private final Protocol bungee;
// 
//     public Protocol toBungee() {
//         return bungee;
//     }
// }


// Path: src/main/java/net/techcable/spudcompat/protocol/injector/AbstractPlayerConnection.java
import java.lang.reflect.Field;
import io.netty.channel.Channel;
import net.md_5.bungee.netty.ChannelWrapper;
import net.md_5.bungee.protocol.MinecraftDecoder;
import net.md_5.bungee.protocol.Protocol;
import net.techcable.spudcompat.protocol.PlayerConnection;
import net.techcable.spudcompat.protocol.ProtocolState;

package net.techcable.spudcompat.protocol.injector;




public abstract class AbstractPlayerConnection implements PlayerConnection {

    @Override
    public void sendPacket(RawPacket rawPacket) {
        getChannelWrapper().write(rawPacket.getAllData());
    }

    @Override
    public Channel getChannel() {
        return getChannelWrapper().getHandle();
    }

    private static final Field minecraftDecoderProtocolField;

    static {
        try {
            minecraftDecoderProtocolField = MinecraftDecoder.class.getDeclaredField("protocol");
            minecraftDecoderProtocolField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            throw new AssertionError("Couldn't find protocol field", e);
        }
    }

    @Override
    public ProtocolState getState() {
        Protocol protocol;
        try {
            protocol = (Protocol) minecraftDecoderProtocolField.get(getChannel().pipeline().get(MinecraftDecoder.class));
        } catch (IllegalAccessException e) {
            throw new AssertionError("Couldn't access protocol field");
        }
        switch (protocol) {
            case GAME:
                return ProtocolState.LOGIN;