public class PacketHandler implements Listener { private final Map handlers = new IdentityHashMap<>(); @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); handlers.put(player, new Handler(player)); } @EventHandler public void onPlayerQuit(PlayerQuitEvent event) { handlers.remove(event.getPlayer()); } public > void onSend(Player player, Class packet, Predicate> predicate) { handlers.get(player).listeners().computeIfAbsent(packet, o -> new ArrayList<>()).add(predicate); } public > void onReceive(Player player, Class packet, Predicate> predicate) { handlers.get(player).listeners().computeIfAbsent(packet, o -> new ArrayList<>()).add(predicate); } } public class Handler extends ChannelDuplexHandler { private final Channel channel; private final Map>, List>>> listeners = new HashMap<>(); public Handler(Player player) { this.channel = ((CraftPlayer) player).getHandle().playerConnection.networkManager.channel; this.channel.pipeline().addBefore("packet_handler", "custom_packet_handler", this); } @Override public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception { final Packet packet = ((Packet) o); final List>> predicates = listeners.get(packet.getClass()); if (predicates == null || predicates.stream().noneMatch(predicate -> predicate.test(packet))) super.channelRead(channelHandlerContext, o); } @Override public void write(ChannelHandlerContext channelHandlerContext, Object o, ChannelPromise channelPromise) throws Exception { final Packet packet = ((Packet) o); final List>> predicates = listeners.get(packet.getClass()); if (predicates == null || predicates.stream().noneMatch(predicate -> predicate.test(packet))) super.write(channelHandlerContext, o, channelPromise); } @Override public void channelUnregistered(ChannelHandlerContext channelHandlerContext) throws Exception { channel.pipeline().remove(this); super.channelUnregistered(channelHandlerContext); } public Map>, List>>> listeners() { return listeners; } }