org.spout.vanilla.protocol.VanillaProtocol.java Source code

Java tutorial

Introduction

Here is the source code for org.spout.vanilla.protocol.VanillaProtocol.java

Source

/*
 * This file is part of Vanilla.
 *
 * Copyright (c) 2011 Spout LLC <http://www.spout.org/>
 * Vanilla is licensed under the Spout License Version 1.
 *
 * Vanilla is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * In addition, 180 days after any changes are published, you can use the
 * software, incorporating those changes, under the terms of the MIT license,
 * as described in the Spout License Version 1.
 *
 * Vanilla is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License,
 * the MIT license and the Spout License Version 1 along with this program.
 * If not, see <http://www.gnu.org/licenses/> for the GNU Lesser General Public
 * License and see <http://spout.in/licensev1> for the full license, including
 * the MIT license.
 */
package org.spout.vanilla.protocol;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.tuple.Pair;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import org.spout.api.Platform;
import org.spout.api.Spout;
import org.spout.api.command.Command;
import org.spout.api.command.CommandArguments;
import org.spout.api.component.entity.PlayerNetworkComponent;
import org.spout.api.exception.ArgumentParseException;
import org.spout.api.exception.UnknownPacketException;
import org.spout.api.map.DefaultedKey;
import org.spout.api.map.DefaultedKeyImpl;
import org.spout.api.protocol.ClientSession;
import org.spout.api.protocol.Message;
import org.spout.api.protocol.MessageCodec;
import org.spout.api.protocol.Protocol;
import org.spout.api.protocol.ServerSession;
import org.spout.api.util.Named;

import org.spout.vanilla.ChatStyle;
import org.spout.vanilla.VanillaPlugin;
import org.spout.vanilla.component.entity.player.VanillaPlayerNetworkComponent;
import org.spout.vanilla.protocol.codec.auth.EncryptionKeyRequestCodec;
import org.spout.vanilla.protocol.codec.auth.EncryptionKeyResponseCodec;
import org.spout.vanilla.protocol.codec.entity.EntityActionCodec;
import org.spout.vanilla.protocol.codec.entity.EntityAnimationCodec;
import org.spout.vanilla.protocol.codec.entity.EntityAttachEntityCodec;
import org.spout.vanilla.protocol.codec.entity.EntityDestroyCodec;
import org.spout.vanilla.protocol.codec.entity.EntityEquipmentCodec;
import org.spout.vanilla.protocol.codec.entity.EntityInitializeCodec;
import org.spout.vanilla.protocol.codec.entity.EntityItemDataCodec;
import org.spout.vanilla.protocol.codec.entity.EntityMetadataCodec;
import org.spout.vanilla.protocol.codec.entity.EntityPropertiesCodec;
import org.spout.vanilla.protocol.codec.entity.EntityRelativePositionCodec;
import org.spout.vanilla.protocol.codec.entity.EntityStatusCodec;
import org.spout.vanilla.protocol.codec.entity.EntityTileDataCodec;
import org.spout.vanilla.protocol.codec.entity.SteerVehicleCodec;
import org.spout.vanilla.protocol.codec.entity.effect.EntityEffectCodec;
import org.spout.vanilla.protocol.codec.entity.effect.EntityRemoveEffectCodec;
import org.spout.vanilla.protocol.codec.entity.pos.EntityHeadYawCodec;
import org.spout.vanilla.protocol.codec.entity.pos.EntityRelativePositionYawCodec;
import org.spout.vanilla.protocol.codec.entity.pos.EntityTeleportCodec;
import org.spout.vanilla.protocol.codec.entity.pos.EntityVelocityCodec;
import org.spout.vanilla.protocol.codec.entity.pos.EntityYawCodec;
import org.spout.vanilla.protocol.codec.entity.spawn.EntityExperienceOrbCodec;
import org.spout.vanilla.protocol.codec.entity.spawn.EntityMobCodec;
import org.spout.vanilla.protocol.codec.entity.spawn.EntityPaintingCodec;
import org.spout.vanilla.protocol.codec.entity.spawn.EntitySpawnObjectCodec;
import org.spout.vanilla.protocol.codec.entity.spawn.EntityThunderboltCodec;
import org.spout.vanilla.protocol.codec.player.PlayerAbilityCodec;
import org.spout.vanilla.protocol.codec.player.PlayerBedCodec;
import org.spout.vanilla.protocol.codec.player.PlayerBlockPlacementCodec;
import org.spout.vanilla.protocol.codec.player.PlayerChatCodec;
import org.spout.vanilla.protocol.codec.player.PlayerCollectItemCodec;
import org.spout.vanilla.protocol.codec.player.PlayerDiggingCodec;
import org.spout.vanilla.protocol.codec.player.PlayerExperienceCodec;
import org.spout.vanilla.protocol.codec.player.PlayerGameStateCodec;
import org.spout.vanilla.protocol.codec.player.PlayerGroundCodec;
import org.spout.vanilla.protocol.codec.player.PlayerHealthCodec;
import org.spout.vanilla.protocol.codec.player.PlayerHeldItemChangeCodec;
import org.spout.vanilla.protocol.codec.player.PlayerLocaleViewDistanceCodec;
import org.spout.vanilla.protocol.codec.player.PlayerStatisticCodec;
import org.spout.vanilla.protocol.codec.player.PlayerStatusCodec;
import org.spout.vanilla.protocol.codec.player.PlayerTabCompleteCodec;
import org.spout.vanilla.protocol.codec.player.PlayerTimeCodec;
import org.spout.vanilla.protocol.codec.player.PlayerUseEntityCodec;
import org.spout.vanilla.protocol.codec.player.conn.PlayerHandshakeCodec;
import org.spout.vanilla.protocol.codec.player.conn.PlayerKickCodec;
import org.spout.vanilla.protocol.codec.player.conn.PlayerListCodec;
import org.spout.vanilla.protocol.codec.player.conn.PlayerLoginRequestCodec;
import org.spout.vanilla.protocol.codec.player.conn.PlayerPingCodec;
import org.spout.vanilla.protocol.codec.player.pos.PlayerLookCodec;
import org.spout.vanilla.protocol.codec.player.pos.PlayerPositionCodec;
import org.spout.vanilla.protocol.codec.player.pos.PlayerPositionLookCodec;
import org.spout.vanilla.protocol.codec.player.pos.PlayerRespawnCodec;
import org.spout.vanilla.protocol.codec.player.pos.PlayerSpawnCodec;
import org.spout.vanilla.protocol.codec.player.pos.PlayerSpawnPositionCodec;
import org.spout.vanilla.protocol.codec.scoreboard.ScoreboardDisplayCodec;
import org.spout.vanilla.protocol.codec.scoreboard.ScoreboardObjectiveCodec;
import org.spout.vanilla.protocol.codec.scoreboard.ScoreboardScoreCodec;
import org.spout.vanilla.protocol.codec.scoreboard.ScoreboardTeamCodec;
import org.spout.vanilla.protocol.codec.server.ServerListPingCodec;
import org.spout.vanilla.protocol.codec.server.ServerPluginCodec;
import org.spout.vanilla.protocol.codec.window.WindowClickCodec;
import org.spout.vanilla.protocol.codec.window.WindowCloseCodec;
import org.spout.vanilla.protocol.codec.window.WindowCreativeActionCodec;
import org.spout.vanilla.protocol.codec.window.WindowEnchantItemCodec;
import org.spout.vanilla.protocol.codec.window.WindowItemsCodec;
import org.spout.vanilla.protocol.codec.window.WindowOpenCodec;
import org.spout.vanilla.protocol.codec.window.WindowPropertyCodec;
import org.spout.vanilla.protocol.codec.window.WindowSlotCodec;
import org.spout.vanilla.protocol.codec.window.WindowTransactionCodec;
import org.spout.vanilla.protocol.codec.world.EffectCodec;
import org.spout.vanilla.protocol.codec.world.ExplosionCodec;
import org.spout.vanilla.protocol.codec.world.ParticleEffectCodec;
import org.spout.vanilla.protocol.codec.world.SoundEffectCodec;
import org.spout.vanilla.protocol.codec.world.block.BlockActionCodec;
import org.spout.vanilla.protocol.codec.world.block.BlockBreakAnimationCodec;
import org.spout.vanilla.protocol.codec.world.block.BlockBulkCodec;
import org.spout.vanilla.protocol.codec.world.block.BlockChangeCodec;
import org.spout.vanilla.protocol.codec.world.block.SignCodec;
import org.spout.vanilla.protocol.codec.world.chunk.ChunkBulkCodec;
import org.spout.vanilla.protocol.codec.world.chunk.ChunkDataCodec;
import org.spout.vanilla.protocol.handler.ServerListPingHandler;
import org.spout.vanilla.protocol.handler.ServerPluginHandler;
import org.spout.vanilla.protocol.handler.auth.EncryptionKeyRequestHandler;
import org.spout.vanilla.protocol.handler.auth.EncryptionKeyResponseHandler;
import org.spout.vanilla.protocol.handler.entity.EntityActionHandler;
import org.spout.vanilla.protocol.handler.entity.EntityAnimationHandler;
import org.spout.vanilla.protocol.handler.entity.EntityAttachEntityHandler;
import org.spout.vanilla.protocol.handler.entity.EntityDestroyHandler;
import org.spout.vanilla.protocol.handler.entity.EntityEffectHandler;
import org.spout.vanilla.protocol.handler.entity.EntityEquipmentHandler;
import org.spout.vanilla.protocol.handler.entity.EntityExperienceOrbHandler;
import org.spout.vanilla.protocol.handler.entity.EntityInitializeHandler;
import org.spout.vanilla.protocol.handler.entity.EntityItemDataHandler;
import org.spout.vanilla.protocol.handler.entity.EntityMetadataHandler;
import org.spout.vanilla.protocol.handler.entity.EntityMobHandler;
import org.spout.vanilla.protocol.handler.entity.EntityObjectHandler;
import org.spout.vanilla.protocol.handler.entity.EntityPaintingHandler;
import org.spout.vanilla.protocol.handler.entity.EntityPropertiesHandler;
import org.spout.vanilla.protocol.handler.entity.EntityStatusHandler;
import org.spout.vanilla.protocol.handler.entity.EntityThunderboltHandler;
import org.spout.vanilla.protocol.handler.entity.EntityTileDataHandler;
import org.spout.vanilla.protocol.handler.entity.SteerVehicleHandler;
import org.spout.vanilla.protocol.handler.entity.effect.EntityRemoveEffectHandler;
import org.spout.vanilla.protocol.handler.entity.pos.EntityHeadYawHandler;
import org.spout.vanilla.protocol.handler.entity.pos.EntityRelativePositionHandler;
import org.spout.vanilla.protocol.handler.entity.pos.EntityRelativePositionYawHandler;
import org.spout.vanilla.protocol.handler.entity.pos.EntityTeleportHandler;
import org.spout.vanilla.protocol.handler.entity.pos.EntityVelocityHandler;
import org.spout.vanilla.protocol.handler.entity.pos.EntityYawHandler;
import org.spout.vanilla.protocol.handler.player.PlayerAbilityHandler;
import org.spout.vanilla.protocol.handler.player.PlayerBedHandler;
import org.spout.vanilla.protocol.handler.player.PlayerBlockPlacementHandler;
import org.spout.vanilla.protocol.handler.player.PlayerChatHandler;
import org.spout.vanilla.protocol.handler.player.PlayerCollectItemHandler;
import org.spout.vanilla.protocol.handler.player.PlayerDiggingHandler;
import org.spout.vanilla.protocol.handler.player.PlayerExperienceHandler;
import org.spout.vanilla.protocol.handler.player.PlayerGameStateHandler;
import org.spout.vanilla.protocol.handler.player.PlayerGroundHandler;
import org.spout.vanilla.protocol.handler.player.PlayerHealthHandler;
import org.spout.vanilla.protocol.handler.player.PlayerHeldItemChangeHandler;
import org.spout.vanilla.protocol.handler.player.PlayerLocaleViewDistanceHandler;
import org.spout.vanilla.protocol.handler.player.PlayerRespawnHandler;
import org.spout.vanilla.protocol.handler.player.PlayerStatisticHandler;
import org.spout.vanilla.protocol.handler.player.PlayerStatusHandler;
import org.spout.vanilla.protocol.handler.player.PlayerTabCompleteHandler;
import org.spout.vanilla.protocol.handler.player.PlayerTimeHandler;
import org.spout.vanilla.protocol.handler.player.PlayerUseEntityHandler;
import org.spout.vanilla.protocol.handler.player.conn.PlayerHandshakeHandler;
import org.spout.vanilla.protocol.handler.player.conn.PlayerKickHandler;
import org.spout.vanilla.protocol.handler.player.conn.PlayerListHandler;
import org.spout.vanilla.protocol.handler.player.conn.PlayerLoginRequestHandler;
import org.spout.vanilla.protocol.handler.player.conn.PlayerPingHandler;
import org.spout.vanilla.protocol.handler.player.pos.PlayerLookHandler;
import org.spout.vanilla.protocol.handler.player.pos.PlayerPositionHandler;
import org.spout.vanilla.protocol.handler.player.pos.PlayerPositionLookHandler;
import org.spout.vanilla.protocol.handler.player.pos.PlayerSpawnHandler;
import org.spout.vanilla.protocol.handler.player.pos.PlayerSpawnPositionHandler;
import org.spout.vanilla.protocol.handler.scoreboard.ScoreboardDisplayHandler;
import org.spout.vanilla.protocol.handler.scoreboard.ScoreboardObjectiveHandler;
import org.spout.vanilla.protocol.handler.scoreboard.ScoreboardScoreHandler;
import org.spout.vanilla.protocol.handler.scoreboard.ScoreboardTeamHandler;
import org.spout.vanilla.protocol.handler.window.WindowClickHandler;
import org.spout.vanilla.protocol.handler.window.WindowCloseHandler;
import org.spout.vanilla.protocol.handler.window.WindowCreativeActionHandler;
import org.spout.vanilla.protocol.handler.window.WindowEnchantItemHandler;
import org.spout.vanilla.protocol.handler.window.WindowItemsHandler;
import org.spout.vanilla.protocol.handler.window.WindowOpenHandler;
import org.spout.vanilla.protocol.handler.window.WindowPropertyHandler;
import org.spout.vanilla.protocol.handler.window.WindowSlotHandler;
import org.spout.vanilla.protocol.handler.window.WindowTransactionHandler;
import org.spout.vanilla.protocol.handler.world.EffectHandler;
import org.spout.vanilla.protocol.handler.world.ExplosionHandler;
import org.spout.vanilla.protocol.handler.world.ParticleEffectHandler;
import org.spout.vanilla.protocol.handler.world.SoundEffectHandler;
import org.spout.vanilla.protocol.handler.world.block.BlockActionHandler;
import org.spout.vanilla.protocol.handler.world.block.BlockBreakAnimationHandler;
import org.spout.vanilla.protocol.handler.world.block.BlockBulkHandler;
import org.spout.vanilla.protocol.handler.world.block.BlockChangeHandler;
import org.spout.vanilla.protocol.handler.world.block.SignHandler;
import org.spout.vanilla.protocol.handler.world.chunk.ChunkBulkHandler;
import org.spout.vanilla.protocol.handler.world.chunk.ChunkDataHandler;
import org.spout.vanilla.protocol.msg.ServerPluginMessage;
import org.spout.vanilla.protocol.msg.player.PlayerChatMessage;
import org.spout.vanilla.protocol.msg.player.conn.PlayerHandshakeMessage;
import org.spout.vanilla.protocol.msg.player.conn.PlayerKickMessage;
import org.spout.vanilla.protocol.netcache.ChunkNetCache;
import org.spout.vanilla.protocol.netcache.protocol.ChunkCacheCodec;
import org.spout.vanilla.protocol.netcache.protocol.ChunkCacheHandler;
import org.spout.vanilla.protocol.plugin.BeaconCodec;
import org.spout.vanilla.protocol.plugin.BeaconHandler;
import org.spout.vanilla.protocol.plugin.CommandBlockCodec;
import org.spout.vanilla.protocol.plugin.CommandBlockHandler;
import org.spout.vanilla.protocol.plugin.RegisterPluginChannelCodec;
import org.spout.vanilla.protocol.plugin.RegisterPluginChannelMessage;
import org.spout.vanilla.protocol.plugin.RegisterPluginChannelMessageHandler;
import org.spout.vanilla.protocol.plugin.UnregisterPluginChannelCodec;
import org.spout.vanilla.protocol.plugin.UnregisterPluginChannelMessageHandler;

public class VanillaProtocol extends Protocol {
    public static final DefaultedKey<String> SESSION_ID = new DefaultedKeyImpl<String>("sessionid",
            "0000000000000000");
    public static final DefaultedKey<String> HANDSHAKE_USERNAME = new DefaultedKeyImpl<String>("handshake_username",
            "");
    public static final DefaultedKey<Long> LOGIN_TIME = new DefaultedKeyImpl<Long>("handshake_time", -1L);
    public static final DefaultedKey<ChunkNetCache> CHUNK_NET_CACHE = new DefaultedKeyImpl<ChunkNetCache>(
            "chunk_net_cache", (ChunkNetCache) null);
    public static final DefaultedKey<ArrayList<String>> REGISTERED_CUSTOM_PACKETS = new DefaultedKey<ArrayList<String>>() {
        private final List<String> defaultRestricted = Arrays.asList("REGISTER", "UNREGISTER");

        public ArrayList<String> getDefaultValue() {
            return new ArrayList<String>(defaultRestricted);
        }

        public String getKeyString() {
            return "registeredPluginChannels";
        }
    };
    public static final int DEFAULT_PORT = 25565;

    public VanillaProtocol() {
        super("Vanilla", DEFAULT_PORT, 512);
        // THIS FORMATTING IS CORRECT NO MATTER WHAT ANY AUTOFORMATTER SAYS. DON'T CHANGE IT
        /* 0x00 */
        registerPacket(PlayerPingCodec.class, new PlayerPingHandler());
        /* 0x01 */
        registerPacket(PlayerLoginRequestCodec.class, new PlayerLoginRequestHandler());
        /* 0x02 */
        registerPacket(PlayerHandshakeCodec.class, new PlayerHandshakeHandler());
        /* 0x03 */
        registerPacket(PlayerChatCodec.class, new PlayerChatHandler());
        /* 0x04 */
        registerPacket(PlayerTimeCodec.class, new PlayerTimeHandler());
        /* 0x05 */
        registerPacket(EntityEquipmentCodec.class, new EntityEquipmentHandler());
        /* 0x06 */
        registerPacket(PlayerSpawnPositionCodec.class, new PlayerSpawnPositionHandler());
        /* 0x07 */
        registerPacket(PlayerUseEntityCodec.class, new PlayerUseEntityHandler());
        /* 0x08 */
        registerPacket(PlayerHealthCodec.class, new PlayerHealthHandler());
        /* 0x09 */
        registerPacket(PlayerRespawnCodec.class, new PlayerRespawnHandler());
        /* 0x0A */
        registerPacket(PlayerGroundCodec.class, new PlayerGroundHandler());
        /* 0x0B */
        registerPacket(PlayerPositionCodec.class, new PlayerPositionHandler());
        /* 0x0C */
        registerPacket(PlayerLookCodec.class, new PlayerLookHandler());
        /* 0x0D */
        registerPacket(PlayerPositionLookCodec.class, new PlayerPositionLookHandler());
        /* 0x0E */
        registerPacket(PlayerDiggingCodec.class, new PlayerDiggingHandler());
        /* 0x0F */
        registerPacket(PlayerBlockPlacementCodec.class, new PlayerBlockPlacementHandler());
        /* 0x10 */
        registerPacket(PlayerHeldItemChangeCodec.class, new PlayerHeldItemChangeHandler());
        /* 0x11 */
        registerPacket(PlayerBedCodec.class, new PlayerBedHandler());
        /* 0x12 */
        registerPacket(EntityAnimationCodec.class, new EntityAnimationHandler());
        /* 0x13 */
        registerPacket(EntityActionCodec.class, new EntityActionHandler());
        /* 0x14 */
        registerPacket(PlayerSpawnCodec.class, new PlayerSpawnHandler());
        /* 0x15 */ //registerPacket(EntityItemCodec.class, new EntityItemHandler()); // Removed as of 1.4.6
        /* 0x16 */
        registerPacket(PlayerCollectItemCodec.class, new PlayerCollectItemHandler());
        /* 0x17 */
        registerPacket(EntitySpawnObjectCodec.class, new EntityObjectHandler());
        /* 0x18 */
        registerPacket(EntityMobCodec.class, new EntityMobHandler());
        /* 0x19 */
        registerPacket(EntityPaintingCodec.class, new EntityPaintingHandler());
        /* 0x1A */
        registerPacket(EntityExperienceOrbCodec.class, new EntityExperienceOrbHandler());
        /* 0x1B */
        registerPacket(SteerVehicleCodec.class, new SteerVehicleHandler());
        /* 0x1C */
        registerPacket(EntityVelocityCodec.class, new EntityVelocityHandler());
        /* 0x1D */
        registerPacket(EntityDestroyCodec.class, new EntityDestroyHandler());
        /* 0x1E */
        registerPacket(EntityInitializeCodec.class, new EntityInitializeHandler()); //TODO the meaning of this packet is basically that the entity did not move/look since the last such packet. We need to implement this!
        /* 0x1F */
        registerPacket(EntityRelativePositionCodec.class, new EntityRelativePositionHandler());
        /* 0x20 */
        registerPacket(EntityYawCodec.class, new EntityYawHandler()); //TODO rename Entity Look on the minecraft protocol page
        /* 0x21 */
        registerPacket(EntityRelativePositionYawCodec.class, new EntityRelativePositionYawHandler()); //TODO same as above
        /* 0x22 */
        registerPacket(EntityTeleportCodec.class, new EntityTeleportHandler());
        /* 0x23 */
        registerPacket(EntityHeadYawCodec.class, new EntityHeadYawHandler()); //TODO same as above
        /* 0x26 */
        registerPacket(EntityStatusCodec.class, new EntityStatusHandler());
        /* 0x27 */
        registerPacket(EntityAttachEntityCodec.class, new EntityAttachEntityHandler());
        /* 0x28 */
        registerPacket(EntityMetadataCodec.class, new EntityMetadataHandler());
        /* 0x29 */
        registerPacket(EntityEffectCodec.class, new EntityEffectHandler());
        /* 0x2A */
        registerPacket(EntityRemoveEffectCodec.class, new EntityRemoveEffectHandler());
        /* 0x2B */
        registerPacket(PlayerExperienceCodec.class, new PlayerExperienceHandler());
        /* 0x2C */
        registerPacket(EntityPropertiesCodec.class, new EntityPropertiesHandler());
        /* 0x33 */
        registerPacket(ChunkDataCodec.class, new ChunkDataHandler()); //TODO rename on the minecraft protocol page
        /* 0x34 */
        registerPacket(BlockBulkCodec.class, new BlockBulkHandler());
        /* 0x35 */
        registerPacket(BlockChangeCodec.class, new BlockChangeHandler());
        /* 0x36 */
        registerPacket(BlockActionCodec.class, new BlockActionHandler());
        /* 0x37 */
        registerPacket(BlockBreakAnimationCodec.class, new BlockBreakAnimationHandler());
        /* 0x38 */
        registerPacket(ChunkBulkCodec.class, new ChunkBulkHandler());
        /* 0x3C */
        registerPacket(ExplosionCodec.class, new ExplosionHandler());
        /* 0x3D */
        registerPacket(EffectCodec.class, new EffectHandler());
        /* 0x3E */
        registerPacket(SoundEffectCodec.class, new SoundEffectHandler());
        /* 0x3F */
        registerPacket(ParticleEffectCodec.class, new ParticleEffectHandler());
        /* 0x46 */
        registerPacket(PlayerGameStateCodec.class, new PlayerGameStateHandler());
        /* 0x47 */
        registerPacket(EntityThunderboltCodec.class, new EntityThunderboltHandler()); //Minecraft protocol page -> Thunderbolt :/
        /* 0x64 */
        registerPacket(WindowOpenCodec.class, new WindowOpenHandler());
        /* 0x65 */
        registerPacket(WindowCloseCodec.class, new WindowCloseHandler());
        /* 0x66 */
        registerPacket(WindowClickCodec.class, new WindowClickHandler());
        /* 0x67 */
        registerPacket(WindowSlotCodec.class, new WindowSlotHandler());
        /* 0x68 */
        registerPacket(WindowItemsCodec.class, new WindowItemsHandler());
        /* 0x69 */
        registerPacket(WindowPropertyCodec.class, new WindowPropertyHandler()); //Update Window Property on the protocol page!
        /* 0x6A */
        registerPacket(WindowTransactionCodec.class, new WindowTransactionHandler());
        /* 0x6B */
        registerPacket(WindowCreativeActionCodec.class, new WindowCreativeActionHandler());
        /* 0x6C */
        registerPacket(WindowEnchantItemCodec.class, new WindowEnchantItemHandler());
        /* 0x82 */
        registerPacket(SignCodec.class, new SignHandler());
        /* 0x83 */
        registerPacket(EntityItemDataCodec.class, new EntityItemDataHandler());
        /* 0x84 */
        registerPacket(EntityTileDataCodec.class, new EntityTileDataHandler()); //Update Tile Entity...
        /* 0xC8 */
        registerPacket(PlayerStatisticCodec.class, new PlayerStatisticHandler());
        /* 0xC9 */
        registerPacket(PlayerListCodec.class, new PlayerListHandler());
        /* 0xCA */
        registerPacket(PlayerAbilityCodec.class, new PlayerAbilityHandler());
        /* 0xCB */
        registerPacket(PlayerTabCompleteCodec.class, new PlayerTabCompleteHandler());
        /* 0xCC */
        registerPacket(PlayerLocaleViewDistanceCodec.class, new PlayerLocaleViewDistanceHandler());
        /* 0xCD */
        registerPacket(PlayerStatusCodec.class, new PlayerStatusHandler());
        /* 0xCE */
        registerPacket(ScoreboardObjectiveCodec.class, new ScoreboardObjectiveHandler());
        /* 0xCF */
        registerPacket(ScoreboardScoreCodec.class, new ScoreboardScoreHandler());
        /* 0xD0 */
        registerPacket(ScoreboardDisplayCodec.class, new ScoreboardDisplayHandler());
        /* 0xD1 */
        registerPacket(ScoreboardTeamCodec.class, new ScoreboardTeamHandler());
        /* 0xFA */
        registerPacket(ServerPluginCodec.class, new ServerPluginHandler());
        /* 0xFC */
        registerPacket(EncryptionKeyResponseCodec.class, new EncryptionKeyResponseHandler());
        /* 0xFD */
        registerPacket(EncryptionKeyRequestCodec.class, new EncryptionKeyRequestHandler());
        /* 0xFE */
        registerPacket(ServerListPingCodec.class, new ServerListPingHandler());
        /* 0xFF */
        registerPacket(PlayerKickCodec.class, new PlayerKickHandler());
        /* PacketFA wrapped packets */
        registerPacket(RegisterPluginChannelCodec.class, new RegisterPluginChannelMessageHandler());
        registerPacket(UnregisterPluginChannelCodec.class, new UnregisterPluginChannelMessageHandler());
        registerPacket(ChunkCacheCodec.class, new ChunkCacheHandler());
        registerPacket(CommandBlockCodec.class, new CommandBlockHandler());
        registerPacket(BeaconCodec.class, new BeaconHandler());
    }

    @Override
    public Message getCommandMessage(String command, CommandArguments args) {
        try {
            if (command.equals("kick")) {
                return getKickMessage(args.popRemainingStrings("message"));
            } else if (command.equals("say")) {
                return new PlayerChatMessage(args.popRemainingStrings("message") + "\u00a7r"); // The reset text is a workaround for a change in 1.3 -- Remove if fixed
            } else {
                return new PlayerChatMessage('/' + command + ' ' + args.popRemainingStrings("message"));
            }
        } catch (ArgumentParseException ex) {
            return new PlayerChatMessage(ChatStyle.RED + ex.getMessage());
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T extends Message> Message getWrappedMessage(T dynamicMessage) throws IOException {
        MessageCodec<T> codec = (MessageCodec<T>) getCodecLookupService().find(dynamicMessage.getClass());
        ByteBuf buffer = codec.encode(Spout.getPlatform() == Platform.CLIENT, dynamicMessage);

        return new ServerPluginMessage(getName(codec), buffer.array());
    }

    @Override
    public MessageCodec<?> readHeader(ByteBuf buf) throws UnknownPacketException {
        int opcode = buf.readUnsignedByte();
        MessageCodec<?> codec = getCodecLookupService().find(opcode);
        if (codec == null) {
            throw new UnknownPacketException(opcode);
        }
        return codec;
    }

    @Override
    public ByteBuf writeHeader(MessageCodec<?> codec, ByteBuf data) {
        ByteBuf buffer = Unpooled.buffer(1);
        buffer.writeByte(codec.getOpcode());
        return buffer;
    }

    @Override
    public Message getKickMessage(String message) {
        return new PlayerKickMessage(message);
    }

    @Override
    public Message getIntroductionMessage(String playerName, InetSocketAddress addr) {
        return new PlayerHandshakeMessage((byte) VanillaPlugin.MINECRAFT_PROTOCOL_ID,
                VanillaPlugin.getInstance().getUsername(), addr.getHostName(), addr.getPort());
    }

    public static MessageCodec<?> getCodec(String name, Protocol activeProtocol) {
        for (Pair<Integer, String> item : activeProtocol.getDynamicallyRegisteredPackets()) {
            MessageCodec<?> codec = activeProtocol.getCodecLookupService().find(item.getLeft());
            if (getName(codec).equalsIgnoreCase(name)) {
                return codec;
            }
        }
        return null;
    }

    public static String getName(MessageCodec<?> codec) {
        if (codec instanceof Named) {
            return ((Named) codec).getName();
        } else {
            return "SPOUT:" + codec.getOpcode();
        }
    }

    @Override
    public Class<? extends PlayerNetworkComponent> getServerNetworkComponent(ServerSession session) {
        return VanillaPlayerNetworkComponent.class;
    }

    @Override
    public Class<? extends PlayerNetworkComponent> getClientNetworkComponent(ClientSession session) {
        return VanillaPlayerNetworkComponent.class;
    }

    @Override
    public void initializeServerSession(ServerSession session) {
        List<MessageCodec<?>> dynamicCodecList = new ArrayList<MessageCodec<?>>();
        for (Pair<Integer, String> item : getDynamicallyRegisteredPackets()) {
            MessageCodec<?> codec = getCodecLookupService().find(item.getLeft());
            if (codec != null) {
                dynamicCodecList.add(codec);
            } else {
                throw new IllegalStateException("Dynamic packet class" + item.getRight()
                        + " claims to be registered but is not in our CodecLookupService!");
            }
        }

        session.send(new RegisterPluginChannelMessage(dynamicCodecList));
    }

    @Override
    public void initializeClientSession(ClientSession session) {
        List<MessageCodec<?>> dynamicCodecList = new ArrayList<MessageCodec<?>>();
        for (Pair<Integer, String> item : getDynamicallyRegisteredPackets()) {
            MessageCodec<?> codec = getCodecLookupService().find(item.getLeft());
            if (codec != null) {
                dynamicCodecList.add(codec);
            } else {
                throw new IllegalStateException("Dynamic packet class" + item.getRight()
                        + " claims to be registered but is not in our CodecLookupService!");
            }
        }
        session.send(new RegisterPluginChannelMessage(dynamicCodecList));
    }
}