[semi-solved] How to insert your own ChannelDuplexHandler so I can listen to all incoming/outcoming packets?


I’ve already coded the handler itself, however, I need a pipeline instance.
That’s how I do that on the client (forge):


How to do the same on Sponge?
(I need this all for listening to specific ping packets and integrating it with vanish)


SpongeAPI does not expose the communication protocol. If you want to listen for packets you have to use the NMS as you did in Forge.
By the way, have you checked the vanish API from SpongeAPI before trying to do your own things?


Well I’ve already done everyting for it, like ForgeGradle workspace.

Nope, and I don’t know what is this :confused: Can’t find info about this API.


Take a look here: https://github.com/SpongePowered/SpongeAPI/blob/22a0adcbf630c28254ae2606bdb0b7659dd06d38/src/main/java/org/spongepowered/api/data/key/Keys.java#L2232 :wink:

The following code should make a player fully vanished:

player.offer(Keys.VANISH, true);
player.offer(Keys.VANISH_IGNORES_COLLISION, true);
player.offer(Keys.VANISH_PREVENTS_TARGETING, true);


Thanks for this code, but will it remove player from ServerListPing, query and LegacyPing (that what I wanted to do, lol)


I don’t think it will by default but it’s probably possible in other parts of the API.
You can still use your own method as you described if you prefer.


My question was initially targeted to NMS, just forgot to say about it.
I’ve also found this example here

NetworkSystem networkSystem = ((MinecraftServer) Sponge.getServer()).getNetworkSystem();
        for (ChannelFuture channelFuture : networkSystem.endpoints) {
            channelFuture.channel().pipeline().addFirst(new CustomChannelInitializer(logger, packetGate));
            logger.info("Successfully injected channel initializer into endpoint");

but it seems to be outdated or something because there’s no field “endpoints” in NetworkSystem anymore


The endpoints field is still there, it’s just private.

I see that PacketGate uses an access transformer to make the field public:

To create an access transformer simply add a file to the META-INF and include this in the buildscript:


Thanks, but it didn’t work :frowning:
Here’s the stacktrace: https://pastebin.com/EsG2KrqC.


Oh, after every change to an access transformer you need to rerun gradle setupDecompWorkspace


Sorry for late reply. It still doesn’t work even afte setupDecompWorkspace


Figured it out myself. Just used pure Reflection without any ATs.

NetworkSystem networkSystem = ((MinecraftServer) Sponge.getServer()).getNetworkSystem();
            Field endpointsField = networkSystem.getClass().getDeclaredField("field_151274_e");
            List<ChannelFuture> endpoints = (List<ChannelFuture>) endpointsField.get(networkSystem);
            for (ChannelFuture channelFuture : endpoints) {
                channelFuture.channel().pipeline().addFirst(new PacketHandler());

However, as the title says now, it’s not completely solved. Method write in my handler is not called, but channelRead is working. I’m adding the handler to the end of the pipeline. So I can see that the client is pinging the server, but I can’t see how the server responds.


Do not do that. ATs were created specifically because reflection breaks all the time.


It has never broken yet. And the problem is already different.