package org.cloudburstmc.protocol.bedrock.codec.v291;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.EntityDataTypeMap;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.*;
import org.cloudburstmc.protocol.bedrock.data.*;
import org.cloudburstmc.protocol.bedrock.data.command.CommandParam;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataFormat;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.*;
import org.cloudburstmc.protocol.bedrock.transformer.BlockDefinitionTransformer;
import org.cloudburstmc.protocol.bedrock.transformer.BooleanTransformer;
import org.cloudburstmc.protocol.bedrock.transformer.StringTransformer;
import org.cloudburstmc.protocol.bedrock.transformer.FlagTransformer;
import org.cloudburstmc.protocol.bedrock.transformer.TypeMapTransformer;
import org.cloudburstmc.protocol.common.util.TypeMap;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Bedrock_v291 {

    protected static final TypeMap<EntityFlag> ENTITY_FLAGS = TypeMap.builder(EntityFlag.class)
            .insert(0, EntityFlag.ON_FIRE)
            .insert(1, EntityFlag.SNEAKING)
            .insert(2, EntityFlag.RIDING)
            .insert(3, EntityFlag.SPRINTING)
            .insert(4, EntityFlag.USING_ITEM)
            .insert(5, EntityFlag.INVISIBLE)
            .insert(6, EntityFlag.TEMPTED)
            .insert(7, EntityFlag.IN_LOVE)
            .insert(8, EntityFlag.SADDLED)
            .insert(9, EntityFlag.POWERED)
            .insert(10, EntityFlag.IGNITED)
            .insert(11, EntityFlag.BABY)
            .insert(12, EntityFlag.CONVERTING)
            .insert(13, EntityFlag.CRITICAL)
            .insert(14, EntityFlag.CAN_SHOW_NAME)
            .insert(15, EntityFlag.ALWAYS_SHOW_NAME)
            .insert(16, EntityFlag.NO_AI)
            .insert(17, EntityFlag.SILENT)
            .insert(18, EntityFlag.WALL_CLIMBING)
            .insert(19, EntityFlag.CAN_CLIMB)
            .insert(20, EntityFlag.CAN_SWIM)
            .insert(21, EntityFlag.CAN_FLY)
            .insert(22, EntityFlag.CAN_WALK)
            .insert(23, EntityFlag.RESTING)
            .insert(24, EntityFlag.SITTING)
            .insert(25, EntityFlag.ANGRY)
            .insert(26, EntityFlag.INTERESTED)
            .insert(27, EntityFlag.CHARGED)
            .insert(28, EntityFlag.TAMED)
            .insert(29, EntityFlag.ORPHANED)
            .insert(30, EntityFlag.LEASHED)
            .insert(31, EntityFlag.SHEARED)
            .insert(32, EntityFlag.GLIDING)
            .insert(33, EntityFlag.ELDER)
            .insert(34, EntityFlag.MOVING)
            .insert(35, EntityFlag.BREATHING)
            .insert(36, EntityFlag.CHESTED)
            .insert(37, EntityFlag.STACKABLE)
            .insert(38, EntityFlag.SHOW_BOTTOM)
            .insert(39, EntityFlag.STANDING)
            .insert(40, EntityFlag.SHAKING)
            .insert(41, EntityFlag.IDLING)
            .insert(42, EntityFlag.CASTING)
            .insert(43, EntityFlag.CHARGING)
            .insert(44, EntityFlag.WASD_CONTROLLED)
            .insert(45, EntityFlag.CAN_POWER_JUMP)
            .insert(46, EntityFlag.LINGERING)
            .insert(47, EntityFlag.HAS_COLLISION)
            .insert(48, EntityFlag.HAS_GRAVITY)
            .insert(49, EntityFlag.FIRE_IMMUNE)
            .insert(50, EntityFlag.DANCING)
            .insert(51, EntityFlag.ENCHANTED)
            .insert(52, EntityFlag.RETURN_TRIDENT)
            .insert(53, EntityFlag.CONTAINER_IS_PRIVATE)
            .insert(54, EntityFlag.IS_TRANSFORMING)
            .insert(55, EntityFlag.DAMAGE_NEARBY_MOBS)
            .insert(56, EntityFlag.SWIMMING)
            .insert(57, EntityFlag.BRIBED)
            .insert(58, EntityFlag.IS_PREGNANT)
            .insert(59, EntityFlag.LAYING_EGG)
            .insert(60, EntityFlag.RIDER_CAN_PICK)
            .build();

    protected static final TypeMap<ParticleType> PARTICLE_TYPES = TypeMap.builder(ParticleType.class)
            .insert(0, ParticleType.UNDEFINED)
            .insert(1, ParticleType.BUBBLE)
            .insert(2, ParticleType.CRIT)
            .insert(3, ParticleType.BLOCK_FORCE_FIELD)
            .insert(4, ParticleType.SMOKE)
            .insert(5, ParticleType.EXPLODE)
            .insert(6, ParticleType.EVAPORATION)
            .insert(7, ParticleType.FLAME)
            .insert(8, ParticleType.LAVA)
            .insert(9, ParticleType.LARGE_SMOKE)
            .insert(10, ParticleType.RED_DUST)
            .insert(11, ParticleType.RISING_BORDER_DUST)
            .insert(12, ParticleType.ICON_CRACK)
            .insert(13, ParticleType.SNOWBALL_POOF)
            .insert(14, ParticleType.LARGE_EXPLODE)
            .insert(15, ParticleType.HUGE_EXPLOSION)
            .insert(16, ParticleType.MOB_FLAME)
            .insert(17, ParticleType.HEART)
            .insert(18, ParticleType.TERRAIN)
            .insert(19, ParticleType.TOWN_AURA)
            .insert(20, ParticleType.PORTAL)
            .insert(21, ParticleType.WATER_SPLASH)
            .insert(22, ParticleType.WATER_WAKE)
            .insert(23, ParticleType.DRIP_WATER)
            .insert(24, ParticleType.DRIP_LAVA)
            .insert(25, ParticleType.FALLING_DUST)
            .insert(26, ParticleType.MOB_SPELL)
            .insert(27, ParticleType.MOB_SPELL_AMBIENT)
            .insert(28, ParticleType.MOB_SPELL_INSTANTANEOUS)
            .insert(29, ParticleType.INK)
            .insert(30, ParticleType.SLIME)
            .insert(31, ParticleType.RAIN_SPLASH)
            .insert(32, ParticleType.VILLAGER_ANGRY)
            .insert(33, ParticleType.VILLAGER_HAPPY)
            .insert(34, ParticleType.ENCHANTING_TABLE)
            .insert(35, ParticleType.TRACKER_EMITTER)
            .insert(36, ParticleType.NOTE)
            .insert(37, ParticleType.WITCH_SPELL)
            .insert(38, ParticleType.CARROT_BOOST)
            .insert(39, ParticleType.MOB_APPEARANCE)
            .insert(40, ParticleType.END_ROD)
            .insert(41, ParticleType.DRAGON_BREATH)
            .insert(42, ParticleType.SPIT)
            .insert(43, ParticleType.TOTEM)
            .insert(44, ParticleType.FOOD)
            .build();

    protected static final EntityDataTypeMap ENTITY_DATA = EntityDataTypeMap.builder()
            .insert(EntityDataTypes.FLAGS, 0, EntityDataFormat.LONG, new FlagTransformer(ENTITY_FLAGS, 0))
            .insert(EntityDataTypes.STRUCTURAL_INTEGRITY, 1, EntityDataFormat.INT)
            .insert(EntityDataTypes.VARIANT, 2, EntityDataFormat.INT)
            .insert(EntityDataTypes.BLOCK, 2, EntityDataFormat.INT, new BlockDefinitionTransformer())
            .insert(EntityDataTypes.COLOR, 3, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.NAME, 4, EntityDataFormat.STRING, StringTransformer.INSTANCE)
            .insert(EntityDataTypes.OWNER_EID, 5, EntityDataFormat.LONG)
            .insert(EntityDataTypes.TARGET_EID, 6, EntityDataFormat.LONG)
            .insert(EntityDataTypes.AIR_SUPPLY, 7, EntityDataFormat.SHORT)
            .insert(EntityDataTypes.EFFECT_COLOR, 8, EntityDataFormat.INT)
            .insert(EntityDataTypes.EFFECT_AMBIENCE, 9, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.JUMP_DURATION, 10, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.HURT_TICKS, 11, EntityDataFormat.INT)
            .insert(EntityDataTypes.HURT_DIRECTION, 12, EntityDataFormat.INT)
            .insert(EntityDataTypes.ROW_TIME_LEFT, 13, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.ROW_TIME_RIGHT, 14, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.VALUE, 15, EntityDataFormat.INT)
            .insert(EntityDataTypes.DISPLAY_BLOCK_STATE, 16, EntityDataFormat.INT, new BlockDefinitionTransformer())
            .insert(EntityDataTypes.DISPLAY_FIREWORK, 16, EntityDataFormat.NBT)
            .insert(EntityDataTypes.HORSE_FLAGS, 16, EntityDataFormat.INT)
            .insert(EntityDataTypes.WITHER_SKULL_DANGEROUS, 16, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.DISPLAY_OFFSET, 17, EntityDataFormat.INT)
            .insert(EntityDataTypes.CUSTOM_DISPLAY, 18, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.HORSE_TYPE, 19, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.OLD_SWELL, 20, EntityDataFormat.INT)
            .insert(EntityDataTypes.SWELL_DIRECTION, 21, EntityDataFormat.INT)
            .insert(EntityDataTypes.CHARGE_AMOUNT, 22, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.CARRY_BLOCK_STATE, 23, EntityDataFormat.INT, new BlockDefinitionTransformer())
            .insert(EntityDataTypes.CLIENT_EVENT, 24, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.USING_ITEM, 25, EntityDataFormat.BYTE, BooleanTransformer.INSTANCE)
            .insert(EntityDataTypes.PLAYER_FLAGS, 26, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.PLAYER_INDEX, 27, EntityDataFormat.INT)
            .insert(EntityDataTypes.BED_POSITION, 28, EntityDataFormat.VECTOR3I)
            .insert(EntityDataTypes.FIREBALL_POWER_X, 29, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.FIREBALL_POWER_Y, 30, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.FIREBALL_POWER_Z, 31, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.AUX_POWER, 32, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.FISH_X, 33, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.FISH_Z, 34, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.FISH_ANGLE, 35, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.AUX_VALUE_DATA, 36, EntityDataFormat.SHORT)
            .insert(EntityDataTypes.LEASH_HOLDER, 37, EntityDataFormat.LONG)
            .insert(EntityDataTypes.SCALE, 38, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.INTERACT_TEXT, 39, EntityDataFormat.STRING, StringTransformer.INSTANCE)
            .insert(EntityDataTypes.SKIN_ID, 40, EntityDataFormat.INT)
            .insert(EntityDataTypes.ACTIONS, 41, EntityDataFormat.STRING)
            .insert(EntityDataTypes.AIR_SUPPLY_MAX, 42, EntityDataFormat.SHORT)
            .insert(EntityDataTypes.MARK_VARIANT, 43, EntityDataFormat.INT)
            .insert(EntityDataTypes.CONTAINER_TYPE, 44, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.CONTAINER_SIZE, 45, EntityDataFormat.INT)
            .insert(EntityDataTypes.CONTAINER_STRENGTH_MODIFIER, 46, EntityDataFormat.INT)
            .insert(EntityDataTypes.BLOCK_TARGET_POS, 47, EntityDataFormat.VECTOR3I)
            .insert(EntityDataTypes.WITHER_INVULNERABLE_TICKS, 48, EntityDataFormat.INT)
            .insert(EntityDataTypes.WITHER_TARGET_A, 49, EntityDataFormat.LONG)
            .insert(EntityDataTypes.WITHER_TARGET_B, 50, EntityDataFormat.LONG)
            .insert(EntityDataTypes.WITHER_TARGET_C, 51, EntityDataFormat.LONG)
            .insert(EntityDataTypes.WITHER_AERIAL_ATTACK, 52, EntityDataFormat.SHORT)
            .insert(EntityDataTypes.WIDTH, 53, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.HEIGHT, 54, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.FUSE_TIME, 55, EntityDataFormat.INT)
            .insert(EntityDataTypes.SEAT_OFFSET, 56, EntityDataFormat.VECTOR3F)
            .insert(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION, 57, EntityDataFormat.BYTE, BooleanTransformer.INSTANCE)
            .insert(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION_DEGREES, 58, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.SEAT_HAS_ROTATION, 59, EntityDataFormat.BYTE, BooleanTransformer.INSTANCE)
            .insert(EntityDataTypes.AREA_EFFECT_CLOUD_RADIUS, 60, EntityDataFormat.FLOAT)
            .insert(EntityDataTypes.AREA_EFFECT_CLOUD_WAITING, 61, EntityDataFormat.INT)
            .insert(EntityDataTypes.AREA_EFFECT_CLOUD_PARTICLE, 62, EntityDataFormat.INT, new TypeMapTransformer<>(PARTICLE_TYPES))
            .insert(EntityDataTypes.SHULKER_PEEK_AMOUNT, 63, EntityDataFormat.INT)
            .insert(EntityDataTypes.SHULKER_ATTACH_FACE, 64, EntityDataFormat.INT)
            .insert(EntityDataTypes.SHULKER_ATTACHED, 65, EntityDataFormat.BYTE, BooleanTransformer.INSTANCE)
            .insert(EntityDataTypes.SHULKER_ATTACH_POS, 66, EntityDataFormat.VECTOR3I)
            .insert(EntityDataTypes.TRADE_TARGET_EID, 67, EntityDataFormat.LONG)
            .insert(EntityDataTypes.CAREER, 68, EntityDataFormat.INT)
            .insert(EntityDataTypes.COMMAND_BLOCK_ENABLED, 69, EntityDataFormat.BYTE, BooleanTransformer.INSTANCE)
            .insert(EntityDataTypes.COMMAND_BLOCK_NAME, 70, EntityDataFormat.STRING)
            .insert(EntityDataTypes.COMMAND_BLOCK_LAST_OUTPUT, 71, EntityDataFormat.STRING)
            .insert(EntityDataTypes.COMMAND_BLOCK_TRACK_OUTPUT, 72, EntityDataFormat.BYTE, BooleanTransformer.INSTANCE)
            .insert(EntityDataTypes.CONTROLLING_RIDER_SEAT_INDEX, 73, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.STRENGTH, 74, EntityDataFormat.INT)
            .insert(EntityDataTypes.STRENGTH_MAX, 75, EntityDataFormat.INT)
            .insert(EntityDataTypes.EVOKER_SPELL_CASTING_COLOR, 76, EntityDataFormat.INT)
            .insert(EntityDataTypes.DATA_LIFETIME_TICKS, 77, EntityDataFormat.INT)
            .insert(EntityDataTypes.ARMOR_STAND_POSE_INDEX, 78, EntityDataFormat.INT)
            .insert(EntityDataTypes.END_CRYSTAL_TICK_OFFSET, 79, EntityDataFormat.INT)
            .insert(EntityDataTypes.NAMETAG_ALWAYS_SHOW, 80, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.COLOR_2, 81, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.NAME_AUTHOR, 82, EntityDataFormat.STRING, StringTransformer.INSTANCE)
            .insert(EntityDataTypes.SCORE, 83, EntityDataFormat.STRING, StringTransformer.INSTANCE)
            .insert(EntityDataTypes.BALLOON_ANCHOR_EID, 84, EntityDataFormat.LONG)
            .insert(EntityDataTypes.PUFFED_STATE, 85, EntityDataFormat.BYTE)
            .insert(EntityDataTypes.BOAT_BUBBLE_TIME, 86, EntityDataFormat.INT)
            .insert(EntityDataTypes.AGENT_EID, 87, EntityDataFormat.LONG)
            .build();

    protected static final TypeMap<Class<?>> GAME_RULE_TYPES = TypeMap.<Class<?>>builder("GameRuleType")
            .insert(1, Boolean.class)
            .insert(2, Integer.class)
            .insert(3, Float.class)
            .build();

    protected static final int LEVEL_EVENT_SOUND = 1000;
    protected static final int LEVEL_EVENT_PARTICLE = 2000;
    protected static final int LEVEL_EVENT_WORLD = 3000;
    protected static final int LEVEL_EVENT_BLOCK = 3500;
    protected static final int LEVEL_EVENT_PARTICLE_TYPE = 0x4000;

    @SuppressWarnings("PointlessArithmeticExpression")
    protected static final TypeMap<LevelEventType> LEVEL_EVENTS = TypeMap.builder(LevelEventType.class)
            .insert(0, LevelEvent.UNDEFINED)
            .insert(LEVEL_EVENT_SOUND + 0, LevelEvent.SOUND_CLICK)
            .insert(LEVEL_EVENT_SOUND + 1, LevelEvent.SOUND_CLICK_FAIL)
            .insert(LEVEL_EVENT_SOUND + 2, LevelEvent.SOUND_LAUNCH)
            .insert(LEVEL_EVENT_SOUND + 3, LevelEvent.SOUND_DOOR_OPEN)
            .insert(LEVEL_EVENT_SOUND + 4, LevelEvent.SOUND_FIZZ)
            .insert(LEVEL_EVENT_SOUND + 5, LevelEvent.SOUND_FUSE)
            .insert(LEVEL_EVENT_SOUND + 6, LevelEvent.SOUND_PLAY_RECORDING)
            .insert(LEVEL_EVENT_SOUND + 7, LevelEvent.SOUND_GHAST_WARNING)
            .insert(LEVEL_EVENT_SOUND + 8, LevelEvent.SOUND_GHAST_FIREBALL)
            .insert(LEVEL_EVENT_SOUND + 9, LevelEvent.SOUND_BLAZE_FIREBALL)
            .insert(LEVEL_EVENT_SOUND + 10, LevelEvent.SOUND_ZOMBIE_DOOR_BUMP)
            .insert(LEVEL_EVENT_SOUND + 12, LevelEvent.SOUND_ZOMBIE_DOOR_CRASH)
            .insert(LEVEL_EVENT_SOUND + 16, LevelEvent.SOUND_ZOMBIE_INFECTED)
            .insert(LEVEL_EVENT_SOUND + 17, LevelEvent.SOUND_ZOMBIE_CONVERTED)
            .insert(LEVEL_EVENT_SOUND + 18, LevelEvent.SOUND_ENDERMAN_TELEPORT)
            .insert(LEVEL_EVENT_SOUND + 20, LevelEvent.SOUND_ANVIL_BROKEN)
            .insert(LEVEL_EVENT_SOUND + 21, LevelEvent.SOUND_ANVIL_USED)
            .insert(LEVEL_EVENT_SOUND + 22, LevelEvent.SOUND_ANVIL_LAND)
            .insert(LEVEL_EVENT_SOUND + 30, LevelEvent.SOUND_INFINITY_ARROW_PICKUP)
            .insert(LEVEL_EVENT_SOUND + 32, LevelEvent.SOUND_TELEPORT_ENDERPEARL)
            .insert(LEVEL_EVENT_SOUND + 40, LevelEvent.SOUND_ITEMFRAME_ITEM_ADD)
            .insert(LEVEL_EVENT_SOUND + 41, LevelEvent.SOUND_ITEMFRAME_BREAK)
            .insert(LEVEL_EVENT_SOUND + 42, LevelEvent.SOUND_ITEMFRAME_PLACE)
            .insert(LEVEL_EVENT_SOUND + 43, LevelEvent.SOUND_ITEMFRAME_ITEM_REMOVE)
            .insert(LEVEL_EVENT_SOUND + 44, LevelEvent.SOUND_ITEMFRAME_ITEM_ROTATE)
            .insert(LEVEL_EVENT_SOUND + 51, LevelEvent.SOUND_EXPERIENCE_ORB_PICKUP)
            .insert(LEVEL_EVENT_SOUND + 52, LevelEvent.SOUND_TOTEM_USED)
            .insert(LEVEL_EVENT_SOUND + 60, LevelEvent.SOUND_ARMOR_STAND_BREAK)
            .insert(LEVEL_EVENT_SOUND + 61, LevelEvent.SOUND_ARMOR_STAND_HIT)
            .insert(LEVEL_EVENT_SOUND + 62, LevelEvent.SOUND_ARMOR_STAND_LAND)
            .insert(LEVEL_EVENT_SOUND + 63, LevelEvent.SOUND_ARMOR_STAND_PLACE)
            .insert(LEVEL_EVENT_PARTICLE + 0, LevelEvent.PARTICLE_SHOOT)
            .insert(LEVEL_EVENT_PARTICLE + 1, LevelEvent.PARTICLE_DESTROY_BLOCK)
            .insert(LEVEL_EVENT_PARTICLE + 2, LevelEvent.PARTICLE_POTION_SPLASH)
            .insert(LEVEL_EVENT_PARTICLE + 3, LevelEvent.PARTICLE_EYE_OF_ENDER_DEATH)
            .insert(LEVEL_EVENT_PARTICLE + 4, LevelEvent.PARTICLE_MOB_BLOCK_SPAWN)
            .insert(LEVEL_EVENT_PARTICLE + 5, LevelEvent.PARTICLE_CROP_GROWTH)
            .insert(LEVEL_EVENT_PARTICLE + 6, LevelEvent.PARTICLE_SOUND_GUARDIAN_GHOST)
            .insert(LEVEL_EVENT_PARTICLE + 7, LevelEvent.PARTICLE_DEATH_SMOKE)
            .insert(LEVEL_EVENT_PARTICLE + 8, LevelEvent.PARTICLE_DENY_BLOCK)
            .insert(LEVEL_EVENT_PARTICLE + 9, LevelEvent.PARTICLE_GENERIC_SPAWN)
            .insert(LEVEL_EVENT_PARTICLE + 10, LevelEvent.PARTICLE_DRAGON_EGG)
            .insert(LEVEL_EVENT_PARTICLE + 11, LevelEvent.PARTICLE_CROP_EATEN)
            .insert(LEVEL_EVENT_PARTICLE + 12, LevelEvent.PARTICLE_CRIT)
            .insert(LEVEL_EVENT_PARTICLE + 13, LevelEvent.PARTICLE_TELEPORT)
            .insert(LEVEL_EVENT_PARTICLE + 14, LevelEvent.PARTICLE_CRACK_BLOCK)
            .insert(LEVEL_EVENT_PARTICLE + 15, LevelEvent.PARTICLE_BUBBLES)
            .insert(LEVEL_EVENT_PARTICLE + 16, LevelEvent.PARTICLE_EVAPORATE)
            .insert(LEVEL_EVENT_PARTICLE + 17, LevelEvent.PARTICLE_DESTROY_ARMOR_STAND)
            .insert(LEVEL_EVENT_PARTICLE + 18, LevelEvent.PARTICLE_BREAKING_EGG)
            .insert(LEVEL_EVENT_PARTICLE + 19, LevelEvent.PARTICLE_DESTROY_EGG)
            .insert(LEVEL_EVENT_PARTICLE + 20, LevelEvent.PARTICLE_EVAPORATE_WATER)
            .insert(LEVEL_EVENT_PARTICLE + 21, LevelEvent.PARTICLE_DESTROY_BLOCK_NO_SOUND)
            .insert(LEVEL_EVENT_WORLD + 1, LevelEvent.START_RAINING)
            .insert(LEVEL_EVENT_WORLD + 2, LevelEvent.START_THUNDERSTORM)
            .insert(LEVEL_EVENT_WORLD + 3, LevelEvent.STOP_RAINING)
            .insert(LEVEL_EVENT_WORLD + 4, LevelEvent.STOP_THUNDERSTORM)
            .insert(LEVEL_EVENT_WORLD + 5, LevelEvent.GLOBAL_PAUSE)
            .insert(LEVEL_EVENT_WORLD + 6, LevelEvent.SIM_TIME_STEP)
            .insert(LEVEL_EVENT_WORLD + 7, LevelEvent.SIM_TIME_SCALE)
            .insert(LEVEL_EVENT_BLOCK + 0, LevelEvent.ACTIVATE_BLOCK)
            .insert(LEVEL_EVENT_BLOCK + 1, LevelEvent.CAULDRON_EXPLODE)
            .insert(LEVEL_EVENT_BLOCK + 2, LevelEvent.CAULDRON_DYE_ARMOR)
            .insert(LEVEL_EVENT_BLOCK + 3, LevelEvent.CAULDRON_CLEAN_ARMOR)
            .insert(LEVEL_EVENT_BLOCK + 4, LevelEvent.CAULDRON_FILL_POTION)
            .insert(LEVEL_EVENT_BLOCK + 5, LevelEvent.CAULDRON_TAKE_POTION)
            .insert(LEVEL_EVENT_BLOCK + 6, LevelEvent.CAULDRON_FILL_WATER)
            .insert(LEVEL_EVENT_BLOCK + 7, LevelEvent.CAULDRON_TAKE_WATER)
            .insert(LEVEL_EVENT_BLOCK + 8, LevelEvent.CAULDRON_ADD_DYE)
            .insert(LEVEL_EVENT_BLOCK + 9, LevelEvent.CAULDRON_CLEAN_BANNER)
            .insert(LEVEL_EVENT_BLOCK + 10, LevelEvent.CAULDRON_FLUSH)
            .insert(LEVEL_EVENT_PARTICLE_TYPE, PARTICLE_TYPES)
            .build();

    protected static final TypeMap<SoundEvent> SOUND_EVENTS = TypeMap.builder(SoundEvent.class)
            .insert(0, SoundEvent.ITEM_USE_ON)
            .insert(1, SoundEvent.HIT)
            .insert(2, SoundEvent.STEP)
            .insert(3, SoundEvent.FLY)
            .insert(4, SoundEvent.JUMP)
            .insert(5, SoundEvent.BREAK)
            .insert(6, SoundEvent.PLACE)
            .insert(7, SoundEvent.HEAVY_STEP)
            .insert(8, SoundEvent.GALLOP)
            .insert(9, SoundEvent.FALL)
            .insert(10, SoundEvent.AMBIENT)
            .insert(11, SoundEvent.AMBIENT_BABY)
            .insert(12, SoundEvent.AMBIENT_IN_WATER)
            .insert(13, SoundEvent.BREATHE)
            .insert(14, SoundEvent.DEATH)
            .insert(15, SoundEvent.DEATH_IN_WATER)
            .insert(16, SoundEvent.DEATH_TO_ZOMBIE)
            .insert(17, SoundEvent.HURT)
            .insert(18, SoundEvent.HURT_IN_WATER)
            .insert(19, SoundEvent.MAD)
            .insert(20, SoundEvent.BOOST)
            .insert(21, SoundEvent.BOW)
            .insert(22, SoundEvent.SQUISH_BIG)
            .insert(23, SoundEvent.SQUISH_SMALL)
            .insert(24, SoundEvent.FALL_BIG)
            .insert(25, SoundEvent.FALL_SMALL)
            .insert(26, SoundEvent.SPLASH)
            .insert(27, SoundEvent.FIZZ)
            .insert(28, SoundEvent.FLAP)
            .insert(29, SoundEvent.SWIM)
            .insert(30, SoundEvent.DRINK)
            .insert(31, SoundEvent.EAT)
            .insert(32, SoundEvent.TAKEOFF)
            .insert(33, SoundEvent.SHAKE)
            .insert(34, SoundEvent.PLOP)
            .insert(35, SoundEvent.LAND)
            .insert(36, SoundEvent.SADDLE)
            .insert(37, SoundEvent.ARMOR)
            .insert(38, SoundEvent.MOB_ARMOR_STAND_PLACE)
            .insert(39, SoundEvent.ADD_CHEST)
            .insert(40, SoundEvent.THROW)
            .insert(41, SoundEvent.ATTACK)
            .insert(42, SoundEvent.ATTACK_NODAMAGE)
            .insert(43, SoundEvent.ATTACK_STRONG)
            .insert(44, SoundEvent.WARN)
            .insert(45, SoundEvent.SHEAR)
            .insert(46, SoundEvent.MILK)
            .insert(47, SoundEvent.THUNDER)
            .insert(48, SoundEvent.EXPLODE)
            .insert(49, SoundEvent.FIRE)
            .insert(50, SoundEvent.IGNITE)
            .insert(51, SoundEvent.FUSE)
            .insert(52, SoundEvent.STARE)
            .insert(53, SoundEvent.SPAWN)
            .insert(54, SoundEvent.SHOOT)
            .insert(55, SoundEvent.BREAK_BLOCK)
            .insert(56, SoundEvent.LAUNCH)
            .insert(57, SoundEvent.BLAST)
            .insert(58, SoundEvent.LARGE_BLAST)
            .insert(59, SoundEvent.TWINKLE)
            .insert(60, SoundEvent.REMEDY)
            .insert(61, SoundEvent.UNFECT)
            .insert(62, SoundEvent.LEVELUP)
            .insert(63, SoundEvent.BOW_HIT)
            .insert(64, SoundEvent.BULLET_HIT)
            .insert(65, SoundEvent.EXTINGUISH_FIRE)
            .insert(66, SoundEvent.ITEM_FIZZ)
            .insert(67, SoundEvent.CHEST_OPEN)
            .insert(68, SoundEvent.CHEST_CLOSED)
            .insert(69, SoundEvent.SHULKERBOX_OPEN)
            .insert(70, SoundEvent.SHULKERBOX_CLOSED)
            .insert(71, SoundEvent.ENDERCHEST_OPEN)
            .insert(72, SoundEvent.ENDERCHEST_CLOSED)
            .insert(73, SoundEvent.POWER_ON)
            .insert(74, SoundEvent.POWER_OFF)
            .insert(75, SoundEvent.ATTACH)
            .insert(76, SoundEvent.DETACH)
            .insert(77, SoundEvent.DENY)
            .insert(78, SoundEvent.TRIPOD)
            .insert(79, SoundEvent.POP)
            .insert(80, SoundEvent.DROP_SLOT)
            .insert(81, SoundEvent.NOTE)
            .insert(82, SoundEvent.THORNS)
            .insert(83, SoundEvent.PISTON_IN)
            .insert(84, SoundEvent.PISTON_OUT)
            .insert(85, SoundEvent.PORTAL)
            .insert(86, SoundEvent.WATER)
            .insert(87, SoundEvent.LAVA_POP)
            .insert(88, SoundEvent.LAVA)
            .insert(89, SoundEvent.BURP)
            .insert(90, SoundEvent.BUCKET_FILL_WATER)
            .insert(91, SoundEvent.BUCKET_FILL_LAVA)
            .insert(92, SoundEvent.BUCKET_EMPTY_WATER)
            .insert(93, SoundEvent.BUCKET_EMPTY_LAVA)
            .insert(94, SoundEvent.ARMOR_EQUIP_CHAIN)
            .insert(95, SoundEvent.ARMOR_EQUIP_DIAMOND)
            .insert(96, SoundEvent.ARMOR_EQUIP_GENERIC)
            .insert(97, SoundEvent.ARMOR_EQUIP_GOLD)
            .insert(98, SoundEvent.ARMOR_EQUIP_IRON)
            .insert(99, SoundEvent.ARMOR_EQUIP_LEATHER)
            .insert(100, SoundEvent.ARMOR_EQUIP_ELYTRA)
            .insert(101, SoundEvent.RECORD_13)
            .insert(102, SoundEvent.RECORD_CAT)
            .insert(103, SoundEvent.RECORD_BLOCKS)
            .insert(104, SoundEvent.RECORD_CHIRP)
            .insert(105, SoundEvent.RECORD_FAR)
            .insert(106, SoundEvent.RECORD_MALL)
            .insert(107, SoundEvent.RECORD_MELLOHI)
            .insert(108, SoundEvent.RECORD_STAL)
            .insert(109, SoundEvent.RECORD_STRAD)
            .insert(110, SoundEvent.RECORD_WARD)
            .insert(111, SoundEvent.RECORD_11)
            .insert(112, SoundEvent.RECORD_WAIT)
            .insert(113, SoundEvent.STOP_RECORD)
            .insert(114, SoundEvent.FLOP)
            .insert(115, SoundEvent.ELDERGUARDIAN_CURSE)
            .insert(116, SoundEvent.MOB_WARNING)
            .insert(117, SoundEvent.MOB_WARNING_BABY)
            .insert(118, SoundEvent.TELEPORT)
            .insert(119, SoundEvent.SHULKER_OPEN)
            .insert(120, SoundEvent.SHULKER_CLOSE)
            .insert(121, SoundEvent.HAGGLE)
            .insert(122, SoundEvent.HAGGLE_YES)
            .insert(123, SoundEvent.HAGGLE_NO)
            .insert(124, SoundEvent.HAGGLE_IDLE)
            .insert(125, SoundEvent.CHORUS_GROW)
            .insert(126, SoundEvent.CHORUS_DEATH)
            .insert(127, SoundEvent.GLASS)
            .insert(128, SoundEvent.POTION_BREWED)
            .insert(129, SoundEvent.CAST_SPELL)
            .insert(130, SoundEvent.PREPARE_ATTACK)
            .insert(131, SoundEvent.PREPARE_SUMMON)
            .insert(132, SoundEvent.PREPARE_WOLOLO)
            .insert(133, SoundEvent.FANG)
            .insert(134, SoundEvent.CHARGE)
            .insert(135, SoundEvent.CAMERA_TAKE_PICTURE)
            .insert(136, SoundEvent.LEASHKNOT_PLACE)
            .insert(137, SoundEvent.LEASHKNOT_BREAK)
            .insert(138, SoundEvent.GROWL)
            .insert(139, SoundEvent.WHINE)
            .insert(140, SoundEvent.PANT)
            .insert(141, SoundEvent.PURR)
            .insert(142, SoundEvent.PURREOW)
            .insert(143, SoundEvent.DEATH_MIN_VOLUME)
            .insert(144, SoundEvent.DEATH_MID_VOLUME)
            .insert(145, SoundEvent.IMITATE_BLAZE)
            .insert(146, SoundEvent.IMITATE_CAVE_SPIDER)
            .insert(147, SoundEvent.IMITATE_CREEPER)
            .insert(148, SoundEvent.IMITATE_ELDER_GUARDIAN)
            .insert(149, SoundEvent.IMITATE_ENDER_DRAGON)
            .insert(150, SoundEvent.IMITATE_ENDERMAN)
            .insert(151, SoundEvent.IMITATE_ENDERMITE)
            .insert(152, SoundEvent.IMITATE_EVOCATION_ILLAGER)
            .insert(153, SoundEvent.IMITATE_GHAST)
            .insert(154, SoundEvent.IMITATE_HUSK)
            .insert(155, SoundEvent.IMITATE_ILLUSION_ILLAGER)
            .insert(156, SoundEvent.IMITATE_MAGMA_CUBE)
            .insert(157, SoundEvent.IMITATE_POLAR_BEAR)
            .insert(158, SoundEvent.IMITATE_SHULKER)
            .insert(159, SoundEvent.IMITATE_SILVERFISH)
            .insert(160, SoundEvent.IMITATE_SKELETON)
            .insert(161, SoundEvent.IMITATE_SLIME)
            .insert(162, SoundEvent.IMITATE_SPIDER)
            .insert(163, SoundEvent.IMITATE_STRAY)
            .insert(164, SoundEvent.IMITATE_VEX)
            .insert(165, SoundEvent.IMITATE_VINDICATION_ILLAGER)
            .insert(166, SoundEvent.IMITATE_WITCH)
            .insert(167, SoundEvent.IMITATE_WITHER)
            .insert(168, SoundEvent.IMITATE_WITHER_SKELETON)
            .insert(169, SoundEvent.IMITATE_WOLF)
            .insert(170, SoundEvent.IMITATE_ZOMBIE)
            .insert(171, SoundEvent.IMITATE_ZOMBIE_PIGMAN)
            .insert(172, SoundEvent.IMITATE_ZOMBIE_VILLAGER)
            .insert(173, SoundEvent.BLOCK_END_PORTAL_FRAME_FILL)
            .insert(174, SoundEvent.BLOCK_END_PORTAL_SPAWN)
            .insert(175, SoundEvent.RANDOM_ANVIL_USE)
            .insert(176, SoundEvent.BOTTLE_DRAGONBREATH)
            .insert(177, SoundEvent.PORTAL_TRAVEL)
            .insert(178, SoundEvent.ITEM_TRIDENT_HIT)
            .insert(179, SoundEvent.ITEM_TRIDENT_RETURN)
            .insert(180, SoundEvent.ITEM_TRIDENT_RIPTIDE_1)
            .insert(181, SoundEvent.ITEM_TRIDENT_RIPTIDE_2)
            .insert(182, SoundEvent.ITEM_TRIDENT_RIPTIDE_3)
            .insert(183, SoundEvent.ITEM_TRIDENT_THROW)
            .insert(184, SoundEvent.ITEM_TRIDENT_THUNDER)
            .insert(185, SoundEvent.ITEM_TRIDENT_HIT_GROUND)
            .insert(186, SoundEvent.DEFAULT)
            .insert(188, SoundEvent.ELEMENT_CONSTRUCTOR_OPEN)
            .insert(189, SoundEvent.ICE_BOMB_HIT)
            .insert(190, SoundEvent.BALLOON_POP)
            .insert(191, SoundEvent.LT_REACTION_ICE_BOMB)
            .insert(192, SoundEvent.LT_REACTION_BLEACH)
            .insert(193, SoundEvent.LT_REACTION_E_PASTE)
            .insert(194, SoundEvent.LT_REACTION_E_PASTE2)
            .insert(199, SoundEvent.LT_REACTION_FERTILIZER)
            .insert(200, SoundEvent.LT_REACTION_FIREBALL)
            .insert(201, SoundEvent.LT_REACTION_MG_SALT)
            .insert(202, SoundEvent.LT_REACTION_MISC_FIRE)
            .insert(203, SoundEvent.LT_REACTION_FIRE)
            .insert(204, SoundEvent.LT_REACTION_MISC_EXPLOSION)
            .insert(205, SoundEvent.LT_REACTION_MISC_MYSTICAL)
            .insert(206, SoundEvent.LT_REACTION_MISC_MYSTICAL2)
            .insert(207, SoundEvent.LT_REACTION_PRODUCT)
            .insert(208, SoundEvent.SPARKLER_USE)
            .insert(209, SoundEvent.GLOWSTICK_USE)
            .insert(210, SoundEvent.SPARKLER_ACTIVE)
            .insert(211, SoundEvent.CONVERT_TO_DROWNED)
            .insert(212, SoundEvent.BUCKET_FILL_FISH)
            .insert(213, SoundEvent.BUCKET_EMPTY_FISH)
            .insert(214, SoundEvent.BUBBLE_UP)
            .insert(215, SoundEvent.BUBBLE_DOWN)
            .insert(216, SoundEvent.BUBBLE_POP)
            .insert(217, SoundEvent.BUBBLE_UP_INSIDE)
            .insert(218, SoundEvent.BUBBLE_DOWN_INSIDE)
            .insert(219, SoundEvent.BABY_HURT)
            .insert(220, SoundEvent.BABY_DEATH)
            .insert(221, SoundEvent.BABY_STEP)
            .insert(222, SoundEvent.BABY_SPAWN)
            .insert(223, SoundEvent.BORN)
            .insert(224, SoundEvent.BLOCK_TURTLE_EGG_BREAK)
            .insert(225, SoundEvent.BLOCK_TURTLE_EGG_CRACK)
            .insert(226, SoundEvent.BLOCK_TURTLE_EGG_HATCH)
            .insert(227, SoundEvent.TURTLE_LAY_EGG)
            .insert(228, SoundEvent.BLOCK_TURTLE_EGG_ATTACK)
            .insert(229, SoundEvent.BEACON_ACTIVATE)
            .insert(230, SoundEvent.BEACON_AMBIENT)
            .insert(231, SoundEvent.BEACON_DEACTIVATE)
            .insert(232, SoundEvent.BEACON_POWER)
            .insert(233, SoundEvent.CONDUIT_ACTIVATE)
            .insert(234, SoundEvent.CONDUIT_AMBIENT)
            .insert(235, SoundEvent.CONDUIT_ATTACK)
            .insert(236, SoundEvent.CONDUIT_DEACTIVATE)
            .insert(237, SoundEvent.CONDUIT_SHORT)
            .insert(238, SoundEvent.SWOOP)
            .insert(239, SoundEvent.UNDEFINED)
            .build();

    protected static final TypeMap<EntityEventType> ENTITY_EVENTS = TypeMap.builder(EntityEventType.class)
            .insert(0, EntityEventType.NONE)
            .insert(1, EntityEventType.JUMP)
            .insert(2, EntityEventType.HURT)
            .insert(3, EntityEventType.DEATH)
            .insert(4, EntityEventType.ATTACK_START)
            .insert(5, EntityEventType.ATTACK_STOP)
            .insert(6, EntityEventType.TAME_FAILED)
            .insert(7, EntityEventType.TAME_SUCCEEDED)
            .insert(8, EntityEventType.SHAKE_WETNESS)
            .insert(9, EntityEventType.USE_ITEM)
            .insert(10, EntityEventType.EAT_GRASS)
            .insert(11, EntityEventType.FISH_HOOK_BUBBLE)
            .insert(12, EntityEventType.FISH_HOOK_POSITION)
            .insert(13, EntityEventType.FISH_HOOK_TIME)
            .insert(14, EntityEventType.FISH_HOOK_TEASE)
            .insert(15, EntityEventType.SQUID_FLEEING)
            .insert(16, EntityEventType.ZOMBIE_VILLAGER_CURE)
            .insert(17, EntityEventType.PLAY_AMBIENT)
            .insert(18, EntityEventType.RESPAWN)
            .insert(19, EntityEventType.GOLEM_FLOWER_OFFER)
            .insert(20, EntityEventType.GOLEM_FLOWER_WITHDRAW)
            .insert(21, EntityEventType.LOVE_PARTICLES)
            .insert(22, EntityEventType.VILLAGER_ANGRY)
            .insert(23, EntityEventType.VILLAGER_HAPPY)
            .insert(24, EntityEventType.WITCH_HAT_MAGIC)
            .insert(25, EntityEventType.FIREWORK_EXPLODE)
            .insert(26, EntityEventType.IN_LOVE_HEARTS)
            .insert(27, EntityEventType.SILVERFISH_MERGE_WITH_STONE)
            .insert(28, EntityEventType.GUARDIAN_ATTACK_ANIMATION)
            .insert(29, EntityEventType.WITCH_DRINK_POTION)
            .insert(30, EntityEventType.WITCH_THROW_POTION)
            .insert(31, EntityEventType.PRIME_TNT_MINECART)
            .insert(32, EntityEventType.PRIME_CREEPER)
            .insert(33, EntityEventType.AIR_SUPPLY)
            .insert(34, EntityEventType.PLAYER_ADD_XP_LEVELS)
            .insert(35, EntityEventType.ELDER_GUARDIAN_CURSE)
            .insert(36, EntityEventType.AGENT_ARM_SWING)
            .insert(37, EntityEventType.ENDER_DRAGON_DEATH)
            .insert(38, EntityEventType.DUST_PARTICLES)
            .insert(39, EntityEventType.ARROW_SHAKE)
            // gap
            .insert(57, EntityEventType.EATING_ITEM)
            .insert(60, EntityEventType.BABY_ANIMAL_FEED)
            .insert(61, EntityEventType.DEATH_SMOKE_CLOUD)
            .insert(62, EntityEventType.COMPLETE_TRADE)
            .insert(63, EntityEventType.REMOVE_LEASH)
            .insert(64, EntityEventType.CARAVAN)
            .insert(65, EntityEventType.CONSUME_TOTEM)
            .insert(66, EntityEventType.CHECK_TREASURE_HUNTER_ACHIEVEMENT)
            .insert(67, EntityEventType.ENTITY_SPAWN)
            .insert(68, EntityEventType.DRAGON_FLAMING)
            .insert(69, EntityEventType.UPDATE_ITEM_STACK_SIZE)
            .insert(70, EntityEventType.START_SWIMMING)
            .insert(71, EntityEventType.BALLOON_POP)
            .insert(72, EntityEventType.TREASURE_HUNT)
            .build();

    public static TypeMap<CommandParam> COMMAND_PARAMS = TypeMap.builder(CommandParam.class)
            .insert(1, CommandParam.INT)
            .insert(2, CommandParam.FLOAT)
            .insert(3, CommandParam.VALUE)
            .insert(4, CommandParam.WILDCARD_INT)
            .insert(5, CommandParam.OPERATOR)
            .insert(6, CommandParam.TARGET)
            .insert(7, CommandParam.WILDCARD_TARGET)
            .insert(24, CommandParam.STRING)
            .insert(26, CommandParam.POSITION)
            .insert(29, CommandParam.MESSAGE)
            .insert(31, CommandParam.TEXT)
            .insert(34, CommandParam.JSON)
            .insert(41, CommandParam.COMMAND)
            .build();

    public static final BedrockCodec CODEC = BedrockCodec.builder()
            .protocolVersion(291)
            .minecraftVersion("1.7.0")
            .helper(() -> new BedrockCodecHelper_v291(ENTITY_DATA, GAME_RULE_TYPES))
            .registerPacket(LoginPacket::new, LoginSerializer_v291.INSTANCE, 1, PacketRecipient.SERVER)
            .registerPacket(PlayStatusPacket::new, PlayStatusSerializer_v291.INSTANCE, 2, PacketRecipient.CLIENT)
            .registerPacket(ServerToClientHandshakePacket::new, ServerToClientHandshakeSerializer_v291.INSTANCE, 3, PacketRecipient.CLIENT)
            .registerPacket(ClientToServerHandshakePacket::new, ClientToServerHandshakeSerializer_v291.INSTANCE, 4, PacketRecipient.SERVER)
            .registerPacket(DisconnectPacket::new, DisconnectSerializer_v291.INSTANCE, 5, PacketRecipient.BOTH)
            .registerPacket(ResourcePacksInfoPacket::new, ResourcePacksInfoSerializer_v291.INSTANCE, 6, PacketRecipient.CLIENT)
            .registerPacket(ResourcePackStackPacket::new, ResourcePackStackSerializer_v291.INSTANCE, 7, PacketRecipient.CLIENT)
            .registerPacket(ResourcePackClientResponsePacket::new, ResourcePackClientResponseSerializer_v291.INSTANCE, 8, PacketRecipient.SERVER)
            .registerPacket(TextPacket::new, TextSerializer_v291.INSTANCE, 9, PacketRecipient.BOTH)
            .registerPacket(SetTimePacket::new, SetTimeSerializer_v291.INSTANCE, 10, PacketRecipient.CLIENT)
            .registerPacket(StartGamePacket::new, StartGameSerializer_v291.INSTANCE, 11, PacketRecipient.CLIENT)
            .registerPacket(AddPlayerPacket::new, AddPlayerSerializer_v291.INSTANCE, 12, PacketRecipient.CLIENT)
            .registerPacket(AddEntityPacket::new, AddEntitySerializer_v291.INSTANCE, 13, PacketRecipient.CLIENT)
            .registerPacket(RemoveEntityPacket::new, RemoveEntitySerializer_v291.INSTANCE, 14, PacketRecipient.CLIENT)
            .registerPacket(AddItemEntityPacket::new, AddItemEntitySerializer_v291.INSTANCE, 15, PacketRecipient.CLIENT)
            .registerPacket(AddHangingEntityPacket::new, AddHangingEntitySerializer_v291.INSTANCE, 16, PacketRecipient.CLIENT)
            .registerPacket(TakeItemEntityPacket::new, TakeItemEntitySerializer_v291.INSTANCE, 17, PacketRecipient.CLIENT)
            .registerPacket(MoveEntityAbsolutePacket::new, MoveEntityAbsoluteSerializer_v291.INSTANCE, 18, PacketRecipient.BOTH)
            .registerPacket(MovePlayerPacket::new, MovePlayerSerializer_v291.INSTANCE, 19, PacketRecipient.BOTH)
            .registerPacket(RiderJumpPacket::new, RiderJumpSerializer_v291.INSTANCE, 20, PacketRecipient.SERVER)
            .registerPacket(UpdateBlockPacket::new, UpdateBlockSerializer_v291.INSTANCE, 21, PacketRecipient.CLIENT)
            .registerPacket(AddPaintingPacket::new, AddPaintingSerializer_v291.INSTANCE, 22, PacketRecipient.CLIENT)
            .registerPacket(ExplodePacket::new, ExplodeSerializer_v291.INSTANCE, 23, PacketRecipient.CLIENT)
            .registerPacket(LevelSoundEvent1Packet::new, new LevelSoundEvent1Serializer_v291(SOUND_EVENTS), 24, PacketRecipient.BOTH)
            .registerPacket(LevelEventPacket::new, new LevelEventSerializer_v291(LEVEL_EVENTS), 25, PacketRecipient.CLIENT)
            .registerPacket(BlockEventPacket::new, BlockEventSerializer_v291.INSTANCE, 26, PacketRecipient.CLIENT)
            .registerPacket(EntityEventPacket::new, new EntityEventSerializer_v291(ENTITY_EVENTS), 27, PacketRecipient.BOTH)
            .registerPacket(MobEffectPacket::new, MobEffectSerializer_v291.INSTANCE, 28, PacketRecipient.CLIENT)
            .registerPacket(UpdateAttributesPacket::new, UpdateAttributesSerializer_v291.INSTANCE, 29, PacketRecipient.CLIENT)
            .registerPacket(InventoryTransactionPacket::new, InventoryTransactionSerializer_v291.INSTANCE, 30, PacketRecipient.BOTH)
            .registerPacket(MobEquipmentPacket::new, MobEquipmentSerializer_v291.INSTANCE, 31, PacketRecipient.BOTH)
            .registerPacket(MobArmorEquipmentPacket::new, MobArmorEquipmentSerializer_v291.INSTANCE, 32, PacketRecipient.BOTH)
            .registerPacket(InteractPacket::new, InteractSerializer_v291.INSTANCE, 33, PacketRecipient.SERVER)
            .registerPacket(BlockPickRequestPacket::new, BlockPickRequestSerializer_v291.INSTANCE, 34, PacketRecipient.SERVER)
            .registerPacket(EntityPickRequestPacket::new, EntityPickRequestSerializer_v291.INSTANCE, 35, PacketRecipient.SERVER)
            .registerPacket(PlayerActionPacket::new, PlayerActionSerializer_v291.INSTANCE, 36, PacketRecipient.BOTH)
            .registerPacket(EntityFallPacket::new, EntityFallSerializer_v291.INSTANCE, 37, PacketRecipient.SERVER)
            .registerPacket(HurtArmorPacket::new, HurtArmorSerializer_v291.INSTANCE, 38, PacketRecipient.CLIENT)
            .registerPacket(SetEntityDataPacket::new, SetEntityDataSerializer_v291.INSTANCE, 39, PacketRecipient.BOTH)
            .registerPacket(SetEntityMotionPacket::new, SetEntityMotionSerializer_v291.INSTANCE, 40, PacketRecipient.BOTH)
            .registerPacket(SetEntityLinkPacket::new, SetEntityLinkSerializer_v291.INSTANCE, 41, PacketRecipient.BOTH)
            .registerPacket(SetHealthPacket::new, SetHealthSerializer_v291.INSTANCE, 42, PacketRecipient.CLIENT)
            .registerPacket(SetSpawnPositionPacket::new, SetSpawnPositionSerializer_v291.INSTANCE, 43, PacketRecipient.CLIENT)
            .registerPacket(AnimatePacket::new, AnimateSerializer_v291.INSTANCE, 44, PacketRecipient.BOTH)
            .registerPacket(RespawnPacket::new, RespawnSerializer_v291.INSTANCE, 45, PacketRecipient.BOTH)
            .registerPacket(ContainerOpenPacket::new, ContainerOpenSerializer_v291.INSTANCE, 46, PacketRecipient.CLIENT)
            .registerPacket(ContainerClosePacket::new, ContainerCloseSerializer_v291.INSTANCE, 47, PacketRecipient.BOTH)
            .registerPacket(PlayerHotbarPacket::new, PlayerHotbarSerializer_v291.INSTANCE, 48, PacketRecipient.BOTH)
            .registerPacket(InventoryContentPacket::new, InventoryContentSerializer_v291.INSTANCE, 49, PacketRecipient.CLIENT)
            .registerPacket(InventorySlotPacket::new, InventorySlotSerializer_v291.INSTANCE, 50, PacketRecipient.CLIENT)
            .registerPacket(ContainerSetDataPacket::new, ContainerSetDataSerializer_v291.INSTANCE, 51, PacketRecipient.CLIENT)
            .registerPacket(CraftingDataPacket::new, CraftingDataSerializer_v291.INSTANCE, 52, PacketRecipient.CLIENT)
            .registerPacket(CraftingEventPacket::new, CraftingEventSerializer_v291.INSTANCE, 53, PacketRecipient.BOTH)
            .registerPacket(GuiDataPickItemPacket::new, GuiDataPickItemSerializer_v291.INSTANCE, 54, PacketRecipient.CLIENT)
            .registerPacket(AdventureSettingsPacket::new, AdventureSettingsSerializer_v291.INSTANCE, 55, PacketRecipient.BOTH)
            .registerPacket(BlockEntityDataPacket::new, BlockEntityDataSerializer_v291.INSTANCE, 56, PacketRecipient.BOTH)
            .registerPacket(PlayerInputPacket::new, PlayerInputSerializer_v291.INSTANCE, 57, PacketRecipient.SERVER)
            .registerPacket(LevelChunkPacket::new, FullChunkDataSerializer_v291.INSTANCE, 58, PacketRecipient.CLIENT)
            .registerPacket(SetCommandsEnabledPacket::new, SetCommandsEnabledSerializer_v291.INSTANCE, 59, PacketRecipient.CLIENT)
            .registerPacket(SetDifficultyPacket::new, SetDifficultySerializer_v291.INSTANCE, 60, PacketRecipient.BOTH)
            .registerPacket(ChangeDimensionPacket::new, ChangeDimensionSerializer_v291.INSTANCE, 61, PacketRecipient.CLIENT)
            .registerPacket(SetPlayerGameTypePacket::new, SetPlayerGameTypeSerializer_v291.INSTANCE, 62, PacketRecipient.BOTH)
            .registerPacket(PlayerListPacket::new, PlayerListSerializer_v291.INSTANCE, 63, PacketRecipient.CLIENT)
            .registerPacket(SimpleEventPacket::new, SimpleEventSerializer_v291.INSTANCE, 64, PacketRecipient.BOTH)
            .registerPacket(EventPacket::new, EventSerializer_v291.INSTANCE, 65, PacketRecipient.CLIENT)
            .registerPacket(SpawnExperienceOrbPacket::new, SpawnExperienceOrbSerializer_v291.INSTANCE, 66, PacketRecipient.CLIENT)
            .registerPacket(ClientboundMapItemDataPacket::new, ClientboundMapItemDataSerializer_v291.INSTANCE, 67, PacketRecipient.CLIENT)
            .registerPacket(MapInfoRequestPacket::new, MapInfoRequestSerializer_v291.INSTANCE, 68, PacketRecipient.SERVER)
            .registerPacket(RequestChunkRadiusPacket::new, RequestChunkRadiusSerializer_v291.INSTANCE, 69, PacketRecipient.SERVER)
            .registerPacket(ChunkRadiusUpdatedPacket::new, ChunkRadiusUpdatedSerializer_v291.INSTANCE, 70, PacketRecipient.CLIENT)
            .registerPacket(ItemFrameDropItemPacket::new, ItemFrameDropItemSerializer_v291.INSTANCE, 71, PacketRecipient.SERVER)
            .registerPacket(GameRulesChangedPacket::new, GameRulesChangedSerializer_v291.INSTANCE, 72, PacketRecipient.CLIENT)
            .registerPacket(CameraPacket::new, CameraSerializer_v291.INSTANCE, 73, PacketRecipient.CLIENT)
            .registerPacket(BossEventPacket::new, BossEventSerializer_v291.INSTANCE, 74, PacketRecipient.BOTH)
            .registerPacket(ShowCreditsPacket::new, ShowCreditsSerializer_v291.INSTANCE, 75, PacketRecipient.BOTH)
            .registerPacket(AvailableCommandsPacket::new, new AvailableCommandsSerializer_v291(COMMAND_PARAMS), 76, PacketRecipient.CLIENT)
            .registerPacket(CommandRequestPacket::new, CommandRequestSerializer_v291.INSTANCE, 77, PacketRecipient.SERVER)
            .registerPacket(CommandBlockUpdatePacket::new, CommandBlockUpdateSerializer_v291.INSTANCE, 78, PacketRecipient.SERVER)
            .registerPacket(CommandOutputPacket::new, CommandOutputSerializer_v291.INSTANCE, 79, PacketRecipient.CLIENT)
            .registerPacket(UpdateTradePacket::new, UpdateTradeSerializer_v291.INSTANCE, 80, PacketRecipient.CLIENT)
            .registerPacket(UpdateEquipPacket::new, UpdateEquipSerializer_v291.INSTANCE, 81, PacketRecipient.CLIENT)
            .registerPacket(ResourcePackDataInfoPacket::new, ResourcePackDataInfoSerializer_v291.INSTANCE, 82, PacketRecipient.CLIENT)
            .registerPacket(ResourcePackChunkDataPacket::new, ResourcePackChunkDataSerializer_v291.INSTANCE, 83, PacketRecipient.CLIENT)
            .registerPacket(ResourcePackChunkRequestPacket::new, ResourcePackChunkRequestSerializer_v291.INSTANCE, 84, PacketRecipient.SERVER)
            .registerPacket(TransferPacket::new, TransferSerializer_v291.INSTANCE, 85, PacketRecipient.CLIENT)
            .registerPacket(PlaySoundPacket::new, PlaySoundSerializer_v291.INSTANCE, 86, PacketRecipient.CLIENT)
            .registerPacket(StopSoundPacket::new, StopSoundSerializer_v291.INSTANCE, 87, PacketRecipient.CLIENT)
            .registerPacket(SetTitlePacket::new, SetTitleSerializer_v291.INSTANCE, 88, PacketRecipient.CLIENT)
            .registerPacket(AddBehaviorTreePacket::new, AddBehaviorTreeSerializer_v291.INSTANCE, 89, PacketRecipient.CLIENT)
            .registerPacket(StructureBlockUpdatePacket::new, StructureBlockUpdateSerializer_v291.INSTANCE, 90, PacketRecipient.SERVER)
            .registerPacket(ShowStoreOfferPacket::new, ShowStoreOfferSerializer_v291.INSTANCE, 91, PacketRecipient.CLIENT)
            .registerPacket(PurchaseReceiptPacket::new, PurchaseReceiptSerializer_v291.INSTANCE, 92, PacketRecipient.SERVER)
            .registerPacket(PlayerSkinPacket::new, PlayerSkinSerializer_v291.INSTANCE, 93, PacketRecipient.BOTH)
            .registerPacket(SubClientLoginPacket::new, SubClientLoginSerializer_v291.INSTANCE, 94, PacketRecipient.SERVER)
            .registerPacket(AutomationClientConnectPacket::new, AutomationClientConnectSerializer_v291.INSTANCE, 95, PacketRecipient.CLIENT)
            .registerPacket(SetLastHurtByPacket::new, SetLastHurtBySerializer_v291.INSTANCE, 96, PacketRecipient.CLIENT)
            .registerPacket(BookEditPacket::new, BookEditSerializer_v291.INSTANCE, 97, PacketRecipient.SERVER)
            .registerPacket(NpcRequestPacket::new, NpcRequestSerializer_v291.INSTANCE, 98, PacketRecipient.SERVER)
            .registerPacket(PhotoTransferPacket::new, PhotoTransferSerializer_v291.INSTANCE, 99, PacketRecipient.CLIENT)
            .registerPacket(ModalFormRequestPacket::new, ModalFormRequestSerializer_v291.INSTANCE, 100, PacketRecipient.CLIENT)
            .registerPacket(ModalFormResponsePacket::new, ModalFormResponseSerializer_v291.INSTANCE, 101, PacketRecipient.SERVER)
            .registerPacket(ServerSettingsRequestPacket::new, ServerSettingsRequestSerializer_v291.INSTANCE, 102, PacketRecipient.SERVER)
            .registerPacket(ServerSettingsResponsePacket::new, ServerSettingsResponseSerializer_v291.INSTANCE, 103, PacketRecipient.CLIENT)
            .registerPacket(ShowProfilePacket::new, ShowProfileSerializer_v291.INSTANCE, 104, PacketRecipient.CLIENT)
            .registerPacket(SetDefaultGameTypePacket::new, SetDefaultGameTypeSerializer_v291.INSTANCE, 105, PacketRecipient.BOTH)
            .registerPacket(RemoveObjectivePacket::new, RemoveObjectiveSerializer_v291.INSTANCE, 106, PacketRecipient.CLIENT)
            .registerPacket(SetDisplayObjectivePacket::new, SetDisplayObjectiveSerializer_v291.INSTANCE, 107, PacketRecipient.CLIENT)
            .registerPacket(SetScorePacket::new, SetScoreSerializer_v291.INSTANCE, 108, PacketRecipient.CLIENT)
            .registerPacket(LabTablePacket::new, LabTableSerializer_v291.INSTANCE, 109, PacketRecipient.BOTH)
            .registerPacket(UpdateBlockSyncedPacket::new, UpdateBlockSyncedSerializer_v291.INSTANCE, 110, PacketRecipient.CLIENT)
            .registerPacket(MoveEntityDeltaPacket::new, MoveEntityDeltaSerializer_v291.INSTANCE, 111, PacketRecipient.CLIENT)
            .registerPacket(SetScoreboardIdentityPacket::new, SetScoreboardIdentitySerializer_v291.INSTANCE, 112, PacketRecipient.CLIENT)
            .registerPacket(SetLocalPlayerAsInitializedPacket::new, SetLocalPlayerAsInitializedSerializer_v291.INSTANCE, 113, PacketRecipient.SERVER)
            .registerPacket(UpdateSoftEnumPacket::new, UpdateSoftEnumSerializer_v291.INSTANCE, 114, PacketRecipient.CLIENT)
            .registerPacket(NetworkStackLatencyPacket::new, NetworkStackLatencySerializer_v291.INSTANCE, 115, PacketRecipient.BOTH)
            .registerPacket(ScriptCustomEventPacket::new, ScriptCustomEventSerializer_v291.INSTANCE, 117, PacketRecipient.BOTH)
            .build();
}
