/**
  * Appends the state of a player's chat to a buffer.
  *
  * @param player the player.
  * @param out the buffer.
  */
 public static void appendChat(Player player, PacketBuffer.WriteBuffer out) {
   out.writeShort(
       ((player.getChatColor() & 0xff) << 8) + (player.getChatEffects() & 0xff),
       PacketBuffer.ByteOrder.LITTLE);
   out.writeByte(player.getStaffRights());
   out.writeByte(player.getChatText().length, PacketBuffer.ValueType.C);
   out.writeBytesReverse(player.getChatText());
 }
  /**
   * Update the primary hitmark block.
   *
   * @param player the player to update for.
   * @param out the packet to write to.
   */
  private static void appendPrimaryHit(Player player, PacketBuffer.WriteBuffer out) {
    out.writeByte(player.getPrimaryHit().getDamage());
    out.writeByte(player.getPrimaryHit().getType().getId(), ValueType.A);

    if (!player.isHasDied()) {
      if (player.getSkills()[Misc.HITPOINTS].getLevel() <= 0) {
        player.getSkills()[Misc.HITPOINTS].setLevel(0);

        try {
          player.setHasDied(true);
          TaskFactory.getFactory().submit(player.death());
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

    out.writeByte(player.getSkills()[Misc.HITPOINTS].getLevel(), ValueType.C);
    out.writeByte(player.getSkills()[Misc.HITPOINTS].getLevelForExperience());
  }
 /**
  * Update the animation block.
  *
  * @param player the player to update for.
  * @param out the packet to write to.
  */
 private static void appendAnimation(Player player, PacketBuffer.WriteBuffer out) {
   out.writeShort(player.getAnimation().getId(), ByteOrder.LITTLE);
   out.writeByte(player.getAnimation().getDelay(), ValueType.C);
 }
  /**
   * Updates the state of a player.
   *
   * @param player the player to update state for.
   * @param block the update block.
   */
  public static void updateState(
      Player player, PacketBuffer.WriteBuffer block, boolean forceAppearance, boolean noChat) {
    /** First we must prepare the mask. */
    int mask = 0x0;

    if (player.getFlags().get(Flag.GRAPHICS)) {
      mask |= 0x100;
    }
    if (player.getFlags().get(Flag.ANIMATION)) {
      mask |= 8;
    }
    if (player.getFlags().get(Flag.FORCED_CHAT)) {
      mask |= 4;
    }
    if (player.getFlags().get(Flag.CHAT) && !noChat) {
      mask |= 0x80;
    }
    if (player.getFlags().get(Flag.APPEARANCE) || forceAppearance) {
      mask |= 0x10;
    }
    if (player.getFlags().get(Flag.FACE_ENTITY)) {
      mask |= 1;
    }
    if (player.getFlags().get(Flag.FACE_COORDINATE)) {
      mask |= 2;
    }
    if (player.getFlags().get(Flag.HIT)) {
      mask |= 0x20;
    }
    if (player.getFlags().get(Flag.HIT_2)) {
      mask |= 0x200;
    }

    /** Now, we write the actual mask. */
    if (mask >= 0x100) {
      mask |= 0x40;
      block.writeShort(mask, PacketBuffer.ByteOrder.LITTLE);
    } else {
      block.writeByte(mask);
    }

    /** Finally, we append the attributes blocks. */
    // Graphics
    if (player.getFlags().get(Flag.GRAPHICS)) {
      appendGfx(player, block);
    }
    // Animation
    if (player.getFlags().get(Flag.ANIMATION)) {
      appendAnimation(player, block);
    }
    // Forced chat
    if (player.getFlags().get(Flag.FORCED_CHAT)) {
      appendForcedChat(player, block);
    }
    // Regular chat
    if (player.getFlags().get(Flag.CHAT) && !noChat) {
      appendChat(player, block);
    }
    // Face entity
    if (player.getFlags().get(Flag.FACE_ENTITY)) {
      appendFaceEntity(player, block);
    }
    // Appearance
    if (player.getFlags().get(Flag.APPEARANCE) || forceAppearance) {
      appendAppearance(player, block);
    }
    // Face coordinates
    if (player.getFlags().get(Flag.FACE_COORDINATE)) {
      appendFaceCoordinate(player, block);
    }
    // Primary hit
    if (player.getFlags().get(Flag.HIT)) {
      appendPrimaryHit(player, block);
    }
    // Secondary hit
    if (player.getFlags().get(Flag.HIT_2)) {
      appendSecondaryHit(player, block);
    }
  }
  /**
   * Appends the state of a player's appearance to a buffer.
   *
   * @param player the player.
   * @param out the buffer.
   */
  public static void appendAppearance(Player player, PacketBuffer.WriteBuffer out) {
    PacketBuffer.WriteBuffer block = PacketBuffer.newWriteBuffer(128);

    /** Gender. */
    block.writeByte(player.getGender()); // Gender

    /** Head icon. */
    block.writeByte(player.getHeadIcon());

    /** Skull icon. */
    block.writeByte(player.getSkullIcon());
    if (player.getNpcAppearanceId() == -1) {

      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_HEAD) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_HEAD));
      } else {
        block.writeByte(0);
      }

      /** Cape. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_CAPE) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_CAPE));
      } else {
        block.writeByte(0);
      }

      /** Amulet. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_AMULET) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_AMULET));
      } else {
        block.writeByte(0);
      }

      /** Weapon. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_WEAPON) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_WEAPON));
      } else {
        block.writeByte(0);
      }

      /** Chest. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_CHEST) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_CHEST));
      } else {
        block.writeShort(0x100 + player.getAppearance()[Misc.APPEARANCE_SLOT_CHEST]);
      }

      /** Shield. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_SHIELD) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_SHIELD));
      } else {
        block.writeByte(0);
      }

      /** Arms. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_CHEST) > 1) {

        if (!Misc.getIsPlatebody()[
            player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_CHEST)]) {
          block.writeShort(0x100 + player.getAppearance()[Misc.APPEARANCE_SLOT_ARMS]);
        } else {
          block.writeByte(0);
        }
      } else {
        block.writeShort(0x100 + player.getAppearance()[Misc.APPEARANCE_SLOT_ARMS]);
      }

      /** Legs. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_LEGS) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_LEGS));
      } else {
        block.writeShort(0x100 + player.getAppearance()[Misc.APPEARANCE_SLOT_LEGS]);
      }

      /** Head. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_HEAD) > 1
          && Misc.getIsFullHelm()[
              player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_HEAD)]) {
        block.writeByte(0);
      } else {
        block.writeShort(0x100 + player.getAppearance()[Misc.APPEARANCE_SLOT_HEAD]);
      }

      /** Hands. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_HANDS) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_HANDS));
      } else {
        block.writeShort(0x100 + player.getAppearance()[Misc.APPEARANCE_SLOT_HANDS]);
      }

      /** Feet. */
      if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_FEET) > 1) {
        block.writeShort(
            0x200 + player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_FEET));
      } else {
        block.writeShort(0x100 + player.getAppearance()[Misc.APPEARANCE_SLOT_FEET]);
      }

      /** Beard. */
      if (player.getGender() == Misc.GENDER_MALE) {
        if (player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_HEAD) > 1
                && !Misc.getIsFullHelm()[
                    player.getEquipment().getContainer().getItemId(Misc.EQUIPMENT_SLOT_HEAD)]
            || player.getEquipment().getContainer().isSlotFree(Misc.EQUIPMENT_SLOT_HEAD)) {
          block.writeShort(0x100 + player.getAppearance()[Misc.APPEARANCE_SLOT_BEARD]);
        } else {
          block.writeByte(0);
        }
      }

    } else {
      block.writeShort(-1);
      block.writeShort(player.getNpcAppearanceId());
    }

    /** Player colors */
    block.writeByte(player.getColors()[0]);
    block.writeByte(player.getColors()[1]);
    block.writeByte(player.getColors()[2]);
    block.writeByte(player.getColors()[3]);
    block.writeByte(player.getColors()[4]);

    /** Movement animations */
    block.writeShort(
        player.getUpdateAnimation().getStandingAnimation() == -1
            ? PlayerAnimation.getStandEmote()
            : player.getUpdateAnimation().getStandingAnimation()); // stand
    block.writeShort(PlayerAnimation.getStandTurnEmote()); // stand turn
    block.writeShort(
        player.getUpdateAnimation().getWalkingAnimation() == -1
            ? PlayerAnimation.getWalkEmote()
            : player.getUpdateAnimation().getWalkingAnimation()); // walk
    block.writeShort(PlayerAnimation.getTurn180Emote()); // turn 180
    block.writeShort(PlayerAnimation.getTurn90CWEmote()); // turn 90 cw
    block.writeShort(PlayerAnimation.getTurn90CCWEmote()); // turn 90 ccw
    block.writeShort(
        player.getUpdateAnimation().getRunningAnimation() == -1
            ? PlayerAnimation.getRunEmote()
            : player.getUpdateAnimation().getRunningAnimation()); // run

    /** Player context menus */
    block.writeLong(Misc.nameToLong(player.getUsername()));
    block.writeByte(player.getCombatLevel());
    block.writeShort(0);

    /** Append the block length and the block to the packet. */
    out.writeByte(block.getBuffer().position(), PacketBuffer.ValueType.C);
    out.writeBytes(block.getBuffer());
  }