package protocolsupport.protocol;

import java.net.InetSocketAddress;

import org.bukkit.entity.Player;

import net.minecraft.server.v1_10_R1.CancelledPacketHandleException;
import net.minecraft.server.v1_10_R1.NetworkManager;
import net.minecraft.server.v1_10_R1.Packet;
import net.minecraft.server.v1_10_R1.PacketListener;
import protocolsupport.api.Connection;
import protocolsupport.api.ProtocolVersion;
import protocolsupport.protocol.pipeline.ChannelHandlers;
import protocolsupport.utils.netty.ChannelUtils;

public class ConnectionImpl extends Connection {

	private final NetworkManager networkmanager;
	public ConnectionImpl(NetworkManager networkmanager, ProtocolVersion version) {
		super(version);
		this.networkmanager = networkmanager;
	}

	@Override
	public Object getNetworkManager() {
		return networkmanager;
	}

	@Override
	public boolean isConnected() {
		return networkmanager.isConnected();
	}

	@Override
	public InetSocketAddress getAddress() {
		return (InetSocketAddress) networkmanager.getSocketAddress();
	}

	@Override
	public Player getPlayer() {
		return ChannelUtils.getBukkitPlayer(networkmanager);
	}

	@Override
	public void receivePacket(Object packet) {
		@SuppressWarnings("unchecked")
		final Packet<PacketListener> packetInst = (Packet<PacketListener>) packet;
		if (networkmanager.channel.isOpen()) {
			try {
				packetInst.a(networkmanager.i());
			} catch (CancelledPacketHandleException ex) {
			}
		}
	}

	@Override
	public void sendPacket(Object packet) {
		@SuppressWarnings("unchecked")
		final Packet<PacketListener> packetInst = (Packet<PacketListener>) packet;
		Runnable packetSend = () -> networkmanager.channel.pipeline().context(ChannelHandlers.ENCODER).write(packetInst);
		if (networkmanager.channel.eventLoop().inEventLoop()) {
			packetSend.run();
		} else {
			networkmanager.channel.eventLoop().submit(packetSend);
		}
	}

	public void setProtocolVersion(ProtocolVersion version) {
		this.version = version;
	}

	public boolean handlePacketSend(Object packet) {
		boolean canSend = true;
		for (PacketSendListener listener : sendListeners) {
			if (!listener.onPacketSending(packet)) {
				canSend = false;
			}
		}
		return canSend;
	}

	public boolean handlePacketReceive(Object packet) {
		boolean canReceive = true;
		for (PacketReceiveListener listener : receiveListeners) {
			if (!listener.onPacketReceiving(packet)) {
				canReceive = false;
			}
		}
		return canReceive;
	}

}

@@ -98,16 +98,111 @@
 layer;%0A%0A
+import io.netty.channel.ChannelHandlerContext;%0Aimport io.netty.channel.ChannelOutboundHandler;%0A
 import n
@@ -1736,333 +1736,688 @@
  -%3E 
-networkmanager.channel.pipeline().context(ChannelHandlers.ENCODER).write(packetInst);%0A%09%09if (networkmanager.channel.eventLoop().inEventLoop()) %7B%0A%09%09%09packetSend.run();%0A%09%09%7D else %7B%0A%09%09%09networkmanager.channel.eventLoop().submit(packetSend);%0A%09%09%7D%0A%09%7D%0A%0A%09public void setProtocolVersion(ProtocolVersion version) %7B%0A%09%09this.version = version
+%7B%0A%09%09%09try %7B%0A%09%09%09%09encoderChannelHandler.write(encoderContext, packetInst, encoderContext.voidPromise());%0A%09%09%09%7D catch (Exception e) %7B%0A%09%09%09%09e.printStackTrace();%0A%09%09%09%7D%0A%09%09%7D;%0A%09%09if (networkmanager.channel.eventLoop().inEventLoop()) %7B%0A%09%09%09packetSend.run();%0A%09%09%7D else %7B%0A%09%09%09networkmanager.channel.eventLoop().submit(packetSend);%0A%09%09%7D%0A%09%7D%0A%0A%09private ChannelHandlerContext encoderContext;%0A%09private ChannelOutboundHandler encoderChannelHandler;%0A%0A%09public void setProtocolVersion(ProtocolVersion version) %7B%0A%09%09this.version = version;%0A%09%09this.encoderContext = networkmanager.channel.pipeline().context(ChannelHandlers.ENCODER);%0A%09%09this.encoderChannelHandler = (ChannelOutboundHandler) encoderContext.handler()
 ;%0A%09%7D

Fix packet send api