private void initSequence(Animation parSequenceIndex) {
    // TODO
    // Should control here which animations are interruptible, in which priority
    // I.e. could reject certain changes depending on what current animation is playing

    // handle case where animation sequence isn't available
    if (mapOfSequences.get(parSequenceIndex) == null) {
      JurassiCraft.instance
          .getLogger()
          .error(
              "Requested an anim id "
                  + parSequenceIndex.toString()
                  + " that doesn't have animation sequence in map for entity "
                  + theEntity.getEntityId());
      currentSequence = Animations.IDLE.get();
      theEntity.setAnimation(Animations.IDLE.get());
    } else if (currentSequence != Animations.IDLE.get()
        && currentSequence == parSequenceIndex) // finished sequence but no new sequence set
    {
      //            JurassiCraft.instance.getLogger().debug("Intializing to idle sequence");
      currentSequence = Animations.IDLE.get();
      theEntity.setAnimation(Animations.IDLE.get());
    } else if (theEntity.isCarcass()) {
      currentSequence = Animations.DYING.get();
    } else {
      currentSequence = parSequenceIndex;
    }
  }
  private void handleFinishedPose() {
    if (incrementCurrentPose()) // increments pose and returns true if finished sequence
    {
      setNextSequence(theEntity.getAnimation());
    }

    updateCurrentPoseArrays();
    setNextPoseModel();
  }
  public void performJabelarAnimations(float parPartialTicks) {

    //        JurassiCraft.instance.getLogger().debug("FPS = " + Minecraft.getDebugFPS() + " and
    // current sequence = " + currentSequence + " and current pose = " + this.currentPose + " and
    // current tick = " + this.currentTickInTween + " out of " + numTicksInTween + " and entity
    // ticks existed = " + theEntity.ticksExisted + " and partial ticks = " + partialTicks);

    performBloodSpurt();

    // Allow interruption of the animation if it is a new animation and not currently dying
    if (theEntity.getAnimation() != currentSequence && currentSequence != Animations.DYING.get()) {
      setNextSequence(theEntity.getAnimation());
    }
    performNextTweenTick();

    partialTicks =
        parPartialTicks; // need to update this after the call because entity ticks are updated one
                         // call after partial ticks
  }
  private void initPoseModel() {
    numPosesInSequence = mapOfSequences.get(currentSequence).length;

    // initialize first pose
    // carcass should init to last pose in dying sequence
    if (theEntity.isCarcass()) {
      currentPose = numPosesInSequence - 1;
    } else {
      currentPose = 0;
    }
    nextPoseModel = arrayOfPoses[mapOfSequences.get(currentSequence)[currentPose][0]];
  }
  private void setNextSequence(Animation parSequenceIndex) {
    // TODO
    // Should control here which animations are interruptible, in which priority
    // I.e. could reject certain changes depending on what current animation is playing

    // handle case where animation sequence isn't available
    if (mapOfSequences.get(parSequenceIndex) == null) {
      JurassiCraft.instance
          .getLogger()
          .error(
              "Requested an anim id "
                  + parSequenceIndex.animationId
                  + " ("
                  + Animations.getAnimation(parSequenceIndex).toString()
                  + ") that doesn't have animation sequence in map for entity "
                  + theEntity.getEntityId());
      currentSequence = Animations.IDLE.get();
    } else if (currentSequence != Animations.IDLE.get()
        && currentSequence == parSequenceIndex) // finished sequence but no new sequence set
    {
      //            JurassiCraft.instance.getLogger().debug("Reverting to idle sequence");
      currentSequence = Animations.IDLE.get();
    } else {
      //            JurassiCraft.instance.getLogger().debug("Setting new sequence to " +
      // parSequenceIndex);
      currentSequence = parSequenceIndex;
    }

    theEntity.setAnimation(currentSequence);
    setNextPoseModel(0);
    startNextTween();

    //        if (currentSequence != Animations.IDLE)
    //        {
    //            JurassiCraft.instance.getLogger().debug("current sequence for entity ID " +
    // theEntity.getEntityId() + " is " + currentSequence + " out of " + mapOfSequences.size() + "
    // and current pose " + currentPose + " out of " + mapOfSequences.get(currentSequence).length +
    // " with " + numTicksInTween + " ticks in tween");
    //        }
  }
  private void initTweenTicks() {
    numTicksInTween = mapOfSequences.get(currentSequence)[currentPose][1];
    // filter out illegal values in array
    if (numTicksInTween < 1) {
      JurassiCraft.instance
          .getLogger()
          .error("Array of sequences has sequence with num ticks illegal value (< 1)");
      numTicksInTween = 1;
    }

    if (theEntity.isCarcass()) {
      currentTickInTween = numTicksInTween - 1;
    } else {
      currentTickInTween = 0;
    }
  }
  // boolean returned indicates if sequence was finished
  public boolean incrementCurrentPose() {
    boolean finishedSequence = false;

    // increment current sequence step
    currentPose++;
    // check if finished sequence
    if (currentPose >= numPosesInSequence) {
      Animations animation = Animations.getAnimation(theEntity.getAnimation());

      if (animation != null && animation.shouldHold()) // hold last dying pose indefinitely
      {
        currentPose--;
      } else {
        currentPose = 0;
        finishedSequence = true;
      }
    }

    //        JurassiCraft.instance.getLogger().debug("Next pose is pose = " + currentPose);
    return finishedSequence;
  }
  private void init(DinosaurModel parModel) {
    initSequence(theEntity.getAnimation());
    //        JurassiCraft.instance.getLogger().info("Initializing to animation sequence = " +
    // currentSequence);
    initPoseModel();
    initTweenTicks();

    // copy passed in model into a model renderer array
    // NOTE: this is the array you will actually animate
    theModelRendererArray = convertPassedInModelToModelRendererArray(parModel);

    // initialize the current pose arrays to match the model renderer array
    currentRotationArray = new float[numParts][3];
    currentPositionArray = new float[numParts][3];
    currentOffsetArray = new float[numParts][3];
    updateCurrentPoseArrays();

    // initialize the increment arrays to match difference between current and next pose
    rotationIncrementArray = new float[numParts][3];
    positionIncrementArray = new float[numParts][3];
    offsetIncrementArray = new float[numParts][3];
    updateIncrementArrays();
  }