package electrosphere.net.parser.net.message;

import electrosphere.net.parser.util.ByteStreamUtils;
import electrosphere.net.parser.net.raw.CircularByteBuffer;
import java.util.LinkedList;
import java.util.List;

public class EntityMessage extends NetworkMessage {

    public enum EntityMessageType {
        CREATE,
        SPAWNCREATURE,
        SPAWNITEM,
        SPAWNOBJECT,
        MOVEUPDATE,
        ATTACKUPDATE,
        STARTATTACK,
        KILL,
        DESTROY,
        SETPROPERTY,
        ATTACHENTITYTOENTITY,
        SPAWNFOLIAGESEED,
        UPDATEENTITYVIEWDIR,
        SYNCPHYSICS,
    }

    EntityMessageType messageType;
    int entityCategory;
    String entitySubtype;
    int entityID;
    String creatureTemplate;
    double positionX;
    double positionY;
    double positionZ;
    double rotationX;
    double rotationY;
    double rotationZ;
    double rotationW;
    double linVelX;
    double linVelY;
    double linVelZ;
    double angVelX;
    double angVelY;
    double angVelZ;
    double linForceX;
    double linForceY;
    double linForceZ;
    double angForceX;
    double angForceY;
    double angForceZ;
    double yaw;
    double pitch;
    double velocity;
    int treeState;
    int propertyType;
    int propertyValue;
    int treeType;
    int treeStatus;
    long time;
    String bone;
    int targetID;
    int bTreeID;
    int propertyID;
    int propertyValueInt;
    float propertyValueFloat;
    double propertyValueDouble;
    String propertyValueString;
    long foliageSeed;

    EntityMessage(EntityMessageType messageType){
        this.type = MessageType.ENTITY_MESSAGE;
        this.messageType = messageType;
    }

    public EntityMessageType getMessageSubtype(){
        return this.messageType;
    }

    public int getentityCategory() {
        return entityCategory;
    }

    public void setentityCategory(int entityCategory) {
        this.entityCategory = entityCategory;
    }

    public String getentitySubtype() {
        return entitySubtype;
    }

    public void setentitySubtype(String entitySubtype) {
        this.entitySubtype = entitySubtype;
    }

    public int getentityID() {
        return entityID;
    }

    public void setentityID(int entityID) {
        this.entityID = entityID;
    }

    public String getcreatureTemplate() {
        return creatureTemplate;
    }

    public void setcreatureTemplate(String creatureTemplate) {
        this.creatureTemplate = creatureTemplate;
    }

    public double getpositionX() {
        return positionX;
    }

    public void setpositionX(double positionX) {
        this.positionX = positionX;
    }

    public double getpositionY() {
        return positionY;
    }

    public void setpositionY(double positionY) {
        this.positionY = positionY;
    }

    public double getpositionZ() {
        return positionZ;
    }

    public void setpositionZ(double positionZ) {
        this.positionZ = positionZ;
    }

    public double getrotationX() {
        return rotationX;
    }

    public void setrotationX(double rotationX) {
        this.rotationX = rotationX;
    }

    public double getrotationY() {
        return rotationY;
    }

    public void setrotationY(double rotationY) {
        this.rotationY = rotationY;
    }

    public double getrotationZ() {
        return rotationZ;
    }

    public void setrotationZ(double rotationZ) {
        this.rotationZ = rotationZ;
    }

    public double getrotationW() {
        return rotationW;
    }

    public void setrotationW(double rotationW) {
        this.rotationW = rotationW;
    }

    public double getlinVelX() {
        return linVelX;
    }

    public void setlinVelX(double linVelX) {
        this.linVelX = linVelX;
    }

    public double getlinVelY() {
        return linVelY;
    }

    public void setlinVelY(double linVelY) {
        this.linVelY = linVelY;
    }

    public double getlinVelZ() {
        return linVelZ;
    }

    public void setlinVelZ(double linVelZ) {
        this.linVelZ = linVelZ;
    }

    public double getangVelX() {
        return angVelX;
    }

    public void setangVelX(double angVelX) {
        this.angVelX = angVelX;
    }

    public double getangVelY() {
        return angVelY;
    }

    public void setangVelY(double angVelY) {
        this.angVelY = angVelY;
    }

    public double getangVelZ() {
        return angVelZ;
    }

    public void setangVelZ(double angVelZ) {
        this.angVelZ = angVelZ;
    }

    public double getlinForceX() {
        return linForceX;
    }

    public void setlinForceX(double linForceX) {
        this.linForceX = linForceX;
    }

    public double getlinForceY() {
        return linForceY;
    }

    public void setlinForceY(double linForceY) {
        this.linForceY = linForceY;
    }

    public double getlinForceZ() {
        return linForceZ;
    }

    public void setlinForceZ(double linForceZ) {
        this.linForceZ = linForceZ;
    }

    public double getangForceX() {
        return angForceX;
    }

    public void setangForceX(double angForceX) {
        this.angForceX = angForceX;
    }

    public double getangForceY() {
        return angForceY;
    }

    public void setangForceY(double angForceY) {
        this.angForceY = angForceY;
    }

    public double getangForceZ() {
        return angForceZ;
    }

    public void setangForceZ(double angForceZ) {
        this.angForceZ = angForceZ;
    }

    public double getyaw() {
        return yaw;
    }

    public void setyaw(double yaw) {
        this.yaw = yaw;
    }

    public double getpitch() {
        return pitch;
    }

    public void setpitch(double pitch) {
        this.pitch = pitch;
    }

    public double getvelocity() {
        return velocity;
    }

    public void setvelocity(double velocity) {
        this.velocity = velocity;
    }

    public int gettreeState() {
        return treeState;
    }

    public void settreeState(int treeState) {
        this.treeState = treeState;
    }

    public int getpropertyType() {
        return propertyType;
    }

    public void setpropertyType(int propertyType) {
        this.propertyType = propertyType;
    }

    public int getpropertyValue() {
        return propertyValue;
    }

    public void setpropertyValue(int propertyValue) {
        this.propertyValue = propertyValue;
    }

    public int gettreeType() {
        return treeType;
    }

    public void settreeType(int treeType) {
        this.treeType = treeType;
    }

    public int gettreeStatus() {
        return treeStatus;
    }

    public void settreeStatus(int treeStatus) {
        this.treeStatus = treeStatus;
    }

    public long gettime() {
        return time;
    }

    public void settime(long time) {
        this.time = time;
    }

    public String getbone() {
        return bone;
    }

    public void setbone(String bone) {
        this.bone = bone;
    }

    public int gettargetID() {
        return targetID;
    }

    public void settargetID(int targetID) {
        this.targetID = targetID;
    }

    public int getbTreeID() {
        return bTreeID;
    }

    public void setbTreeID(int bTreeID) {
        this.bTreeID = bTreeID;
    }

    public int getpropertyID() {
        return propertyID;
    }

    public void setpropertyID(int propertyID) {
        this.propertyID = propertyID;
    }

    public int getpropertyValueInt() {
        return propertyValueInt;
    }

    public void setpropertyValueInt(int propertyValueInt) {
        this.propertyValueInt = propertyValueInt;
    }

    public float getpropertyValueFloat() {
        return propertyValueFloat;
    }

    public void setpropertyValueFloat(float propertyValueFloat) {
        this.propertyValueFloat = propertyValueFloat;
    }

    public double getpropertyValueDouble() {
        return propertyValueDouble;
    }

    public void setpropertyValueDouble(double propertyValueDouble) {
        this.propertyValueDouble = propertyValueDouble;
    }

    public String getpropertyValueString() {
        return propertyValueString;
    }

    public void setpropertyValueString(String propertyValueString) {
        this.propertyValueString = propertyValueString;
    }

    public long getfoliageSeed() {
        return foliageSeed;
    }

    public void setfoliageSeed(long foliageSeed) {
        this.foliageSeed = foliageSeed;
    }

    static void stripPacketHeader(CircularByteBuffer byteBuffer){
        byteBuffer.read(2);
    }

    public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
        switch(secondByte){
            case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE:
                return EntityMessage.canParseCreateMessage(byteBuffer);
            case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE:
                return EntityMessage.canParseSpawnCreatureMessage(byteBuffer);
            case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNITEM:
                return EntityMessage.canParseSpawnItemMessage(byteBuffer);
            case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNOBJECT:
                return EntityMessage.canParseSpawnObjectMessage(byteBuffer);
            case TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE:
                if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE:
                if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_STARTATTACK:
                if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_STARTATTACK_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_KILL:
                if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_KILL_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY:
                if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY:
                if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY:
                return EntityMessage.canParseattachEntityToEntityMessage(byteBuffer);
            case TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED:
                return EntityMessage.canParseSpawnFoliageSeedMessage(byteBuffer);
            case TypeBytes.ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR:
                if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_SYNCPHYSICS:
                if(byteBuffer.getRemaining() >= TypeBytes.ENTITY_MESSAGE_TYPE_SYNCPHYSICS_SIZE){
                    return true;
                } else {
                    return false;
                }
        }
        return false;
    }

    public static boolean canParseCreateMessage(CircularByteBuffer byteBuffer){
        int currentStreamLength = byteBuffer.getRemaining();
        List<Byte> temporaryByteQueue = new LinkedList<Byte>();
        if(currentStreamLength < 6){
            return false;
        }
        if(currentStreamLength < 10){
            return false;
        }
        int entitySubtypeSize = 0;
        if(currentStreamLength < 14){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(10 + 0));
            temporaryByteQueue.add(byteBuffer.peek(10 + 1));
            temporaryByteQueue.add(byteBuffer.peek(10 + 2));
            temporaryByteQueue.add(byteBuffer.peek(10 + 3));
            entitySubtypeSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 14 + entitySubtypeSize){
            return false;
        }
        if(currentStreamLength < 22 + entitySubtypeSize){
            return false;
        }
        if(currentStreamLength < 30 + entitySubtypeSize){
            return false;
        }
        if(currentStreamLength < 38 + entitySubtypeSize){
            return false;
        }
        return true;
    }

    public static EntityMessage parseCreateMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.CREATE);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setentityCategory(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setentitySubtype(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructCreateMessage(int entityID,int entityCategory,String entitySubtype,double positionX,double positionY,double positionZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.CREATE);
        rVal.setentityID(entityID);
        rVal.setentityCategory(entityCategory);
        rVal.setentitySubtype(entitySubtype);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.serialize();
        return rVal;
    }

    public static boolean canParseSpawnCreatureMessage(CircularByteBuffer byteBuffer){
        int currentStreamLength = byteBuffer.getRemaining();
        List<Byte> temporaryByteQueue = new LinkedList<Byte>();
        if(currentStreamLength < 6){
            return false;
        }
        int creatureTemplateSize = 0;
        if(currentStreamLength < 10){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(6 + 0));
            temporaryByteQueue.add(byteBuffer.peek(6 + 1));
            temporaryByteQueue.add(byteBuffer.peek(6 + 2));
            temporaryByteQueue.add(byteBuffer.peek(6 + 3));
            creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 10 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 18 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 26 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 34 + creatureTemplateSize){
            return false;
        }
        return true;
    }

    public static EntityMessage parseSpawnCreatureMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNCREATURE);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructSpawnCreatureMessage(int entityID,String creatureTemplate,double positionX,double positionY,double positionZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNCREATURE);
        rVal.setentityID(entityID);
        rVal.setcreatureTemplate(creatureTemplate);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.serialize();
        return rVal;
    }

    public static boolean canParseSpawnItemMessage(CircularByteBuffer byteBuffer){
        int currentStreamLength = byteBuffer.getRemaining();
        List<Byte> temporaryByteQueue = new LinkedList<Byte>();
        if(currentStreamLength < 6){
            return false;
        }
        int creatureTemplateSize = 0;
        if(currentStreamLength < 10){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(6 + 0));
            temporaryByteQueue.add(byteBuffer.peek(6 + 1));
            temporaryByteQueue.add(byteBuffer.peek(6 + 2));
            temporaryByteQueue.add(byteBuffer.peek(6 + 3));
            creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 10 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 18 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 26 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 34 + creatureTemplateSize){
            return false;
        }
        return true;
    }

    public static EntityMessage parseSpawnItemMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNITEM);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructSpawnItemMessage(int entityID,String creatureTemplate,double positionX,double positionY,double positionZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNITEM);
        rVal.setentityID(entityID);
        rVal.setcreatureTemplate(creatureTemplate);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.serialize();
        return rVal;
    }

    public static boolean canParseSpawnObjectMessage(CircularByteBuffer byteBuffer){
        int currentStreamLength = byteBuffer.getRemaining();
        List<Byte> temporaryByteQueue = new LinkedList<Byte>();
        if(currentStreamLength < 6){
            return false;
        }
        int creatureTemplateSize = 0;
        if(currentStreamLength < 10){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(6 + 0));
            temporaryByteQueue.add(byteBuffer.peek(6 + 1));
            temporaryByteQueue.add(byteBuffer.peek(6 + 2));
            temporaryByteQueue.add(byteBuffer.peek(6 + 3));
            creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 10 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 18 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 26 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 34 + creatureTemplateSize){
            return false;
        }
        return true;
    }

    public static EntityMessage parseSpawnObjectMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNOBJECT);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructSpawnObjectMessage(int entityID,String creatureTemplate,double positionX,double positionY,double positionZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNOBJECT);
        rVal.setentityID(entityID);
        rVal.setcreatureTemplate(creatureTemplate);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parsemoveUpdateMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.MOVEUPDATE);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationW(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setvelocity(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpropertyValueInt(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.settreeState(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructmoveUpdateMessage(int entityID,long time,double positionX,double positionY,double positionZ,double rotationX,double rotationY,double rotationZ,double rotationW,double velocity,int propertyValueInt,int treeState){
        EntityMessage rVal = new EntityMessage(EntityMessageType.MOVEUPDATE);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.setrotationX(rotationX);
        rVal.setrotationY(rotationY);
        rVal.setrotationZ(rotationZ);
        rVal.setrotationW(rotationW);
        rVal.setvelocity(velocity);
        rVal.setpropertyValueInt(propertyValueInt);
        rVal.settreeState(treeState);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseattackUpdateMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACKUPDATE);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setvelocity(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.settreeState(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructattackUpdateMessage(int entityID,long time,double positionX,double positionY,double positionZ,double rotationX,double rotationY,double rotationZ,double velocity,int treeState){
        EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACKUPDATE);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.setrotationX(rotationX);
        rVal.setrotationY(rotationY);
        rVal.setrotationZ(rotationZ);
        rVal.setvelocity(velocity);
        rVal.settreeState(treeState);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parsestartAttackMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.STARTATTACK);
        stripPacketHeader(byteBuffer);
        return rVal;
    }

    public static EntityMessage constructstartAttackMessage(){
        EntityMessage rVal = new EntityMessage(EntityMessageType.STARTATTACK);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseKillMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.KILL);
        stripPacketHeader(byteBuffer);
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructKillMessage(long time,int entityID){
        EntityMessage rVal = new EntityMessage(EntityMessageType.KILL);
        rVal.settime(time);
        rVal.setentityID(entityID);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseDestroyMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.DESTROY);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructDestroyMessage(int entityID){
        EntityMessage rVal = new EntityMessage(EntityMessageType.DESTROY);
        rVal.setentityID(entityID);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parsesetPropertyMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETPROPERTY);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
        rVal.setpropertyType(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setpropertyValue(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructsetPropertyMessage(int entityID,long time,int propertyType,int propertyValue){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETPROPERTY);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpropertyType(propertyType);
        rVal.setpropertyValue(propertyValue);
        rVal.serialize();
        return rVal;
    }

    public static boolean canParseattachEntityToEntityMessage(CircularByteBuffer byteBuffer){
        int currentStreamLength = byteBuffer.getRemaining();
        List<Byte> temporaryByteQueue = new LinkedList<Byte>();
        if(currentStreamLength < 6){
            return false;
        }
        int boneSize = 0;
        if(currentStreamLength < 10){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(6 + 0));
            temporaryByteQueue.add(byteBuffer.peek(6 + 1));
            temporaryByteQueue.add(byteBuffer.peek(6 + 2));
            temporaryByteQueue.add(byteBuffer.peek(6 + 3));
            boneSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 10 + boneSize){
            return false;
        }
        if(currentStreamLength < 14 + boneSize){
            return false;
        }
        return true;
    }

    public static EntityMessage parseattachEntityToEntityMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACHENTITYTOENTITY);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setbone(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        rVal.settargetID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructattachEntityToEntityMessage(int entityID,String bone,int targetID){
        EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACHENTITYTOENTITY);
        rVal.setentityID(entityID);
        rVal.setbone(bone);
        rVal.settargetID(targetID);
        rVal.serialize();
        return rVal;
    }

    public static boolean canParseSpawnFoliageSeedMessage(CircularByteBuffer byteBuffer){
        int currentStreamLength = byteBuffer.getRemaining();
        List<Byte> temporaryByteQueue = new LinkedList<Byte>();
        if(currentStreamLength < 6){
            return false;
        }
        int creatureTemplateSize = 0;
        if(currentStreamLength < 10){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(6 + 0));
            temporaryByteQueue.add(byteBuffer.peek(6 + 1));
            temporaryByteQueue.add(byteBuffer.peek(6 + 2));
            temporaryByteQueue.add(byteBuffer.peek(6 + 3));
            creatureTemplateSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 10 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 18 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 26 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 34 + creatureTemplateSize){
            return false;
        }
        if(currentStreamLength < 42 + creatureTemplateSize){
            return false;
        }
        return true;
    }

    public static EntityMessage parseSpawnFoliageSeedMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNFOLIAGESEED);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setcreatureTemplate(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        rVal.setfoliageSeed(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructSpawnFoliageSeedMessage(int entityID,String creatureTemplate,long foliageSeed,double positionX,double positionY,double positionZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SPAWNFOLIAGESEED);
        rVal.setentityID(entityID);
        rVal.setcreatureTemplate(creatureTemplate);
        rVal.setfoliageSeed(foliageSeed);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseupdateEntityViewDirMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.UPDATEENTITYVIEWDIR);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
        rVal.setpropertyType(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setyaw(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpitch(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructupdateEntityViewDirMessage(int entityID,long time,int propertyType,double yaw,double pitch){
        EntityMessage rVal = new EntityMessage(EntityMessageType.UPDATEENTITYVIEWDIR);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpropertyType(propertyType);
        rVal.setyaw(yaw);
        rVal.setpitch(pitch);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parsesyncPhysicsMessage(CircularByteBuffer byteBuffer){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SYNCPHYSICS);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setrotationW(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setlinVelX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setlinVelY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setlinVelZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setangVelX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setangVelY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setangVelZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setlinForceX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setlinForceY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setlinForceZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setangForceX(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setangForceY(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        rVal.setangForceZ(ByteStreamUtils.popDoubleFromByteQueue(byteBuffer));
        return rVal;
    }

    public static EntityMessage constructsyncPhysicsMessage(int entityID,long time,double positionX,double positionY,double positionZ,double rotationX,double rotationY,double rotationZ,double rotationW,double linVelX,double linVelY,double linVelZ,double angVelX,double angVelY,double angVelZ,double linForceX,double linForceY,double linForceZ,double angForceX,double angForceY,double angForceZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SYNCPHYSICS);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.setrotationX(rotationX);
        rVal.setrotationY(rotationY);
        rVal.setrotationZ(rotationZ);
        rVal.setrotationW(rotationW);
        rVal.setlinVelX(linVelX);
        rVal.setlinVelY(linVelY);
        rVal.setlinVelZ(linVelZ);
        rVal.setangVelX(angVelX);
        rVal.setangVelY(angVelY);
        rVal.setangVelZ(angVelZ);
        rVal.setlinForceX(linForceX);
        rVal.setlinForceY(linForceY);
        rVal.setlinForceZ(linForceZ);
        rVal.setangForceX(angForceX);
        rVal.setangForceY(angForceY);
        rVal.setangForceZ(angForceZ);
        rVal.serialize();
        return rVal;
    }

    @Override
    void serialize(){
        byte[] intValues = new byte[8];
        byte[] stringBytes;
        switch(this.messageType){
            case CREATE:
                rawBytes = new byte[2+4+4+4+entitySubtype.length()+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_CREATE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(entityCategory);
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(entitySubtype.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[10+i] = intValues[i];
                }
                stringBytes = entitySubtype.getBytes();
                for(int i = 0; i < entitySubtype.length(); i++){
                    rawBytes[14+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+entitySubtype.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+entitySubtype.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+entitySubtype.length()+i] = intValues[i];
                }
                break;
            case SPAWNCREATURE:
                rawBytes = new byte[2+4+4+creatureTemplate.length()+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNCREATURE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(creatureTemplate.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                stringBytes = creatureTemplate.getBytes();
                for(int i = 0; i < creatureTemplate.length(); i++){
                    rawBytes[10+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[10+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[18+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[26+creatureTemplate.length()+i] = intValues[i];
                }
                break;
            case SPAWNITEM:
                rawBytes = new byte[2+4+4+creatureTemplate.length()+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNITEM;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(creatureTemplate.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                stringBytes = creatureTemplate.getBytes();
                for(int i = 0; i < creatureTemplate.length(); i++){
                    rawBytes[10+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[10+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[18+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[26+creatureTemplate.length()+i] = intValues[i];
                }
                break;
            case SPAWNOBJECT:
                rawBytes = new byte[2+4+4+creatureTemplate.length()+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNOBJECT;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(creatureTemplate.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                stringBytes = creatureTemplate.getBytes();
                for(int i = 0; i < creatureTemplate.length(); i++){
                    rawBytes[10+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[10+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[18+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[26+creatureTemplate.length()+i] = intValues[i];
                }
                break;
            case MOVEUPDATE:
                rawBytes = new byte[2+4+8+8+8+8+8+8+8+8+8+4+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationX);
                for(int i = 0; i < 8; i++){
                    rawBytes[38+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationY);
                for(int i = 0; i < 8; i++){
                    rawBytes[46+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[54+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationW);
                for(int i = 0; i < 8; i++){
                    rawBytes[62+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(velocity);
                for(int i = 0; i < 8; i++){
                    rawBytes[70+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(propertyValueInt);
                for(int i = 0; i < 4; i++){
                    rawBytes[78+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(treeState);
                for(int i = 0; i < 4; i++){
                    rawBytes[82+i] = intValues[i];
                }
                break;
            case ATTACKUPDATE:
                rawBytes = new byte[2+4+8+8+8+8+8+8+8+8+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationX);
                for(int i = 0; i < 8; i++){
                    rawBytes[38+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationY);
                for(int i = 0; i < 8; i++){
                    rawBytes[46+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[54+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(velocity);
                for(int i = 0; i < 8; i++){
                    rawBytes[62+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(treeState);
                for(int i = 0; i < 4; i++){
                    rawBytes[70+i] = intValues[i];
                }
                break;
            case STARTATTACK:
                rawBytes = new byte[2];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_STARTATTACK;
                break;
            case KILL:
                rawBytes = new byte[2+8+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_KILL;
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[10+i] = intValues[i];
                }
                break;
            case DESTROY:
                rawBytes = new byte[2+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                break;
            case SETPROPERTY:
                rawBytes = new byte[2+4+8+4+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(propertyType);
                for(int i = 0; i < 4; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(propertyValue);
                for(int i = 0; i < 4; i++){
                    rawBytes[18+i] = intValues[i];
                }
                break;
            case ATTACHENTITYTOENTITY:
                rawBytes = new byte[2+4+4+bone.length()+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(bone.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                stringBytes = bone.getBytes();
                for(int i = 0; i < bone.length(); i++){
                    rawBytes[10+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(targetID);
                for(int i = 0; i < 4; i++){
                    rawBytes[10+bone.length()+i] = intValues[i];
                }
                break;
            case SPAWNFOLIAGESEED:
                rawBytes = new byte[2+4+4+creatureTemplate.length()+8+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SPAWNFOLIAGESEED;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(creatureTemplate.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                stringBytes = creatureTemplate.getBytes();
                for(int i = 0; i < creatureTemplate.length(); i++){
                    rawBytes[10+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(foliageSeed);
                for(int i = 0; i < 8; i++){
                    rawBytes[10+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[18+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[26+creatureTemplate.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[34+creatureTemplate.length()+i] = intValues[i];
                }
                break;
            case UPDATEENTITYVIEWDIR:
                rawBytes = new byte[2+4+8+4+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_UPDATEENTITYVIEWDIR;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(propertyType);
                for(int i = 0; i < 4; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(yaw);
                for(int i = 0; i < 8; i++){
                    rawBytes[18+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(pitch);
                for(int i = 0; i < 8; i++){
                    rawBytes[26+i] = intValues[i];
                }
                break;
            case SYNCPHYSICS:
                rawBytes = new byte[2+4+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SYNCPHYSICS;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationX);
                for(int i = 0; i < 8; i++){
                    rawBytes[38+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationY);
                for(int i = 0; i < 8; i++){
                    rawBytes[46+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[54+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(rotationW);
                for(int i = 0; i < 8; i++){
                    rawBytes[62+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(linVelX);
                for(int i = 0; i < 8; i++){
                    rawBytes[70+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(linVelY);
                for(int i = 0; i < 8; i++){
                    rawBytes[78+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(linVelZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[86+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(angVelX);
                for(int i = 0; i < 8; i++){
                    rawBytes[94+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(angVelY);
                for(int i = 0; i < 8; i++){
                    rawBytes[102+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(angVelZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[110+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(linForceX);
                for(int i = 0; i < 8; i++){
                    rawBytes[118+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(linForceY);
                for(int i = 0; i < 8; i++){
                    rawBytes[126+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(linForceZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[134+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(angForceX);
                for(int i = 0; i < 8; i++){
                    rawBytes[142+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(angForceY);
                for(int i = 0; i < 8; i++){
                    rawBytes[150+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(angForceZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[158+i] = intValues[i];
                }
                break;
        }
        serialized = true;
    }

}
