Skip to content

Shadow (AntiCheat)


This feature of LabyMod is still in development and may not be entirely stable.


By using this protocol called SHADOW you can access the client's movement input keys. This protocol provides you the ability to improve the server side anticheat!

Enabling the protocol

The client will send you this information on join in the labymod3:main channel
Message key: INFO

   "version": "3.4.2",
   "ccp": {},
   "shadow": {  
      "enabled": true,
      "version": 1
   "addons": []

The server should answer on the labymod3:shadow channel just an id that is an integer.


We changed the plugin channel name from SHADOW to labymod3:shadow since LabyMod 3.8.0 to support the latest Minecraft 1.16 version

There are following valid id's:

0: Reset the packet counter to zero.
1: Enable the protocol for this client
2: Disable the protocol for this client

Now you can setup the pipeline transformer for the new protocol:

EntityPlayer entityPlayer = ( ( CraftPlayer ) player ).getHandle();
Channel channel =;
ChannelPipeline pipeline = channel.pipeline();
pipeline.addAfter( "decoder", "shadowpacketin", new PacketPlayerIn( ) );

Example code of server

import net.minecraft.server.v1_8_R3.PacketDataSerializer;
import net.minecraft.server.v1_8_R3.PacketPlayInCustomPayload;
import net.minecraft.server.v1_8_R3.PacketPlayInFlying;
import net.minecraft.server.v1_8_R3.PacketPlayInFlying.PacketPlayInLook;
import net.minecraft.server.v1_8_R3.PacketPlayInFlying.PacketPlayInPosition;
import net.minecraft.server.v1_8_R3.PacketPlayInFlying.PacketPlayInPositionLook;

public class PacketPlayerIn extends ChannelInboundHandlerAdapter {

    public void channelRead( ChannelHandlerContext ctx, Object msg ) throws Exception {
         // Is incoming packet a custom payload?
        if ( msg instanceof PacketPlayInCustomPayload ) {
            PacketPlayInCustomPayload packet = ( PacketPlayInCustomPayload ) msg;

            // Is channel name labymod3:shadow?
            String channel = packet.a();
            if ( channel.equals( "labymod3:shadow" ) ) {
                PacketDataSerializer data = packet.b();

                // First byte is the shadow packet id
                byte id = data.readByte();

                switch ( id ) {
                    case 0x00: // PacketPlayInPosition
                        double x = data.readDouble();
                        double y = data.readDouble();
                        double z = data.readDouble();
                        boolean onGround = data.readBoolean();

                        PacketPlayInPosition packetPlayInPosition = new PacketPlayInPosition();
                        setValue( PacketPlayInFlying.class, packetPlayInPosition, "x", x );
                        setValue( PacketPlayInFlying.class, packetPlayInPosition, "y", y );
                        setValue( PacketPlayInFlying.class, packetPlayInPosition, "z", z );
                        setValue( PacketPlayInFlying.class, packetPlayInPosition, "f", onGround );
                        super.channelRead( ctx, packetPlayInPosition );

                    case 0x01: // PacketPlayInLook
                        float yaw = data.readFloat();
                        float pitch = data.readFloat();
                        onGround = data.readBoolean();

                        PacketPlayInLook packetPlayInLook = new PacketPlayInLook();
                        setValue( PacketPlayInFlying.class, packetPlayInLook, "yaw", yaw );
                        setValue( PacketPlayInFlying.class, packetPlayInLook, "pitch", pitch );
                        setValue( PacketPlayInFlying.class, packetPlayInLook, "f", onGround );
                        super.channelRead( ctx, packetPlayInLook );

                    case 0x02: // PacketPlayInPositionLook
                        x = data.readDouble();
                        y = data.readDouble();
                        z = data.readDouble();
                        yaw = data.readFloat();
                        pitch = data.readFloat();
                        onGround = data.readBoolean();

                        PacketPlayInPositionLook packetPlayInPositionLook = new PacketPlayInPositionLook();
                        setValue( PacketPlayInFlying.class, packetPlayInPositionLook, "x", x );
                        setValue( PacketPlayInFlying.class, packetPlayInPositionLook, "y", y );
                        setValue( PacketPlayInFlying.class, packetPlayInPositionLook, "z", z );
                        setValue( PacketPlayInFlying.class, packetPlayInPositionLook, "yaw", yaw );
                        setValue( PacketPlayInFlying.class, packetPlayInPositionLook, "pitch", pitch );
                        setValue( PacketPlayInFlying.class, packetPlayInPositionLook, "f", onGround );
                        super.channelRead( ctx, packetPlayInPositionLook );

                    case 0x03: // PacketPlayInFlying
                        onGround = data.readBoolean();

                        PacketPlayInFlying packetPlayInFlying = new PacketPlayInFlying();
                        setValue( PacketPlayInFlying.class, packetPlayInFlying, "f", onGround );
                        super.channelRead( ctx, packetPlayInFlying );


                  // Timestamp of client at this packet
                long time = data.readLong();

                // Read all movement inputs
                double moveForward = data.readDouble();
                double moveStrafe = data.readDouble();
                boolean jump = data.readBoolean();
                boolean sneak = data.readBoolean();
                double x = data.readDouble();
                double y = data.readDouble();
                double z = data.readDouble();
                float yaw = data.readFloat();
                float pitch = data.readFloat();
                boolean sprinting = data.readBoolean();

                // Packet counter since join
                int packetCounter = data.readInt();

                  // Handle data
                handleInput( time, moveForward, moveStrafe, jump, sneak, x, y, z, yaw, pitch, sprinting, packetCounter );

                  // Cancel this packet

        // This packet can pass
        super.channelRead( ctx, msg );

    private void setValue( Class clazz, Object instance, String field, Object value ) throws Exception {
        Field f = clazz.getDeclaredField( field );
        f.setAccessible( true );
        f.set( instance, value );