Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-73837

Entity movement collision check should respect riding entities bounding box

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • None
    • Minecraft 1.8.1-pre3
    • None
    • Unconfirmed

      When riding a horse, players can easily ride through two block high archways because only the horses bounding box is checked for movement collision detection. This leads to the player's head getting stuck in the ceiling and getting suffocation damage. This also happens when in a room of three blocks height and you accidently ride on a chest.

      This can actually be easily fixed - and I did so for our own server mod - by using the unified bounding box of both entity AND its rider when doing its movement checks. This is my solution done in the MCP 9.10 code:

      Entity.java
          /** 
           * New method I added to obtain unified bounding box of entity
           * and its eventual rider. Bounding box of rider needs to be
           * corrected for sitting position or else we get stuck in
           * minecarts, because players full bounding box lowers into the floor
           */
          public AxisAlignedBB getEntityWithRiderBoundingBox()
          {
          	return this.riddenByEntity != null 
              		? this.boundingBox.union(
              				new AxisAlignedBB(
              						this.riddenByEntity.boundingBox.minX,
              						this.riddenByEntity.boundingBox.minY - this.riddenByEntity.getYOffset(),
              						this.riddenByEntity.boundingBox.minZ,
              						this.riddenByEntity.boundingBox.maxX,
              						this.riddenByEntity.boundingBox.maxY,
              						this.riddenByEntity.boundingBox.maxZ))
              		: this.boundingBox;
          }
      
         /**
           * This is the method in Entity.java that handles the movement collisions
           */
          public void moveEntity(double x, double y, double z)
          {
              /* Stuff that handles sneaking player not dropping off
               * ledges omitted here */
      
                 AxisAlignedBB entityBB = this.getEntityBoundingBox();
                 AxisAlignedBB riddenBB = this.getEntityWithRiderBoundingBox();
      
                  List var53 = this.worldObj.getCollidingBoundingBoxes(this, riddenBB.addCoord(x, y, z));
                  AxisAlignedBB var23;
                  
                 /*
                  * Here we perform all checks with the new _unified_ bounding box
                  * and update the entity's own bounding box only when needed
                  */
                  for (Iterator var22 = var53.iterator(); var22.hasNext(); y = var23.calculateYOffset(riddenBB, y))
                  {
                      var23 = (AxisAlignedBB)var22.next();
                  }
      
                  riddenBB = riddenBB.offset(0.0D, y, 0.0D);
                  boolean var54 = this.onGround || var15 != y && var15 < 0.0D;
                  AxisAlignedBB var24;
                  Iterator var55;
      
                  for (var55 = var53.iterator(); var55.hasNext(); x = var24.calculateXOffset(riddenBB, x))
                  {
                      var24 = (AxisAlignedBB)var55.next();
                  }
      
                  riddenBB = riddenBB.offset(x, 0.0D, 0.0D);
      
                  for (var55 = var53.iterator(); var55.hasNext(); z = var24.calculateZOffset(riddenBB, z))
                  {
                      var24 = (AxisAlignedBB)var55.next();
                  }
      
                  riddenBB = riddenBB.offset(0.0D, 0.0D, z);
                  entityBB = entityBB.offset(x, y, z);
      
                  if (this.stepHeight > 0.0F && var54 && (var13 != x || var17 != z))
                  {
                      double var56 = x;
                      double var25 = y;
                      double var27 = z;
                      AxisAlignedBB var29 = entityBB;
                      entityBB = this.getEntityBoundingBox();
                      riddenBB = this.getEntityWithRiderBoundingBox();
                      y = (double)this.stepHeight;
                      List var30 = this.worldObj.getCollidingBoundingBoxes(this, riddenBB.addCoord(var13, y, var17));
                      AxisAlignedBB var31 = riddenBB;
                      AxisAlignedBB var31b = entityBB;
                      AxisAlignedBB var32 = var31.addCoord(var13, 0.0D, var17);
                      AxisAlignedBB var32b = var31b.addCoord(var13, 0.0D, var17);
                      double var33 = y;
                      AxisAlignedBB var36;
      
                      for (Iterator var35 = var30.iterator(); var35.hasNext(); var33 = var36.calculateYOffset(var32, var33))
                      {
                          var36 = (AxisAlignedBB)var35.next();
                      }
      
                      var31 = var31.offset(0.0D, var33, 0.0D);
                      var31b = var31b.offset(0.0D, var33, 0.0D);
                      double var67 = var13;
                      AxisAlignedBB var38;
      
                      for (Iterator var37 = var30.iterator(); var37.hasNext(); var67 = var38.calculateXOffset(var31, var67))
                      {
                          var38 = (AxisAlignedBB)var37.next();
                      }
      
                      var31 = var31.offset(var67, 0.0D, 0.0D);
                      var31b = var31b.offset(var67, 0.0D, 0.0D);
                      double var68 = var17;
                      AxisAlignedBB var40;
      
                      for (Iterator var39 = var30.iterator(); var39.hasNext(); var68 = var40.calculateZOffset(var31, var68))
                      {
                          var40 = (AxisAlignedBB)var39.next();
                      }
      
                      var31 = var31.offset(0.0D, 0.0D, var68);
                      var31b = var31b.offset(0.0D, 0.0D, var68);
                      
                      AxisAlignedBB var69 = riddenBB;
                      AxisAlignedBB var69b = entityBB;
                      double var70 = y;
                      AxisAlignedBB var43;
      
                      for (Iterator var42 = var30.iterator(); var42.hasNext(); var70 = var43.calculateYOffset(var69, var70))
                      {
                          var43 = (AxisAlignedBB)var42.next();
                      }
      
                      var69 = var69.offset(0.0D, var70, 0.0D);
                      double var71 = var13;
                      AxisAlignedBB var45;
      
                      for (Iterator var44 = var30.iterator(); var44.hasNext(); var71 = var45.calculateXOffset(var69, var71))
                      {
                          var45 = (AxisAlignedBB)var44.next();
                      }
      
                      var69 = var69.offset(var71, 0.0D, 0.0D);
                      double var72 = var17;
                      AxisAlignedBB var47;
      
                      for (Iterator var46 = var30.iterator(); var46.hasNext(); var72 = var47.calculateZOffset(var69, var72))
                      {
                          var47 = (AxisAlignedBB)var46.next();
                      }
      
                      var69 = var69.offset(0.0D, 0.0D, var72);
                      var69b = var69b.offset(var71, var70, var72);
                      double var73 = var67 * var67 + var68 * var68;
                      double var48 = var71 * var71 + var72 * var72;
      
                      if (var73 > var48)
                      {
                          x = var67;
                          z = var68;
                          riddenBB = var31;
                          entityBB = var31b;
                      }
                      else
                      {
                          x = var71;
                          z = var72;
                          riddenBB = var69;
                          entityBB = var69b;
                      }
      
                      y = (double)(-this.stepHeight);
                      AxisAlignedBB var51;
      
                      for (Iterator var50 = var30.iterator(); var50.hasNext(); y = var51.calculateYOffset(riddenBB, y))
                      {
                          var51 = (AxisAlignedBB)var50.next();
                      }
      
                      entityBB = entityBB.offset(0.0D, y, 0.0D);
      
                      if (var56 * var56 + var27 * var27 >= x * x + z * z)
                      {
                          x = var56;
                          y = var25;
                          z = var27;
                          entityBB = var29;
                      }
                  }
      
                  /* 
                   * Finally we write back the new bounding box to the entity
                   * by what's probably .setEntityBoundingBox() in the original code
                   */
                  this.func_174826_a(entityBB);
      
                  /*
                   * Those following lines just quoted to make it easy to find 
                   * the code
                   */
                  this.worldObj.theProfiler.endSection();
                  this.worldObj.theProfiler.startSection("rest");
      

      The effect is, that while ridden, a horse won't move into any space only two blocks high or the player's head getting stuck in the ceiling when jumping in a room. A small side effect: no more riding through low hanging leave blocks either, but that's a small price to pay, I think.

            Unassigned Unassigned
            Rondaru Markus Pfefferle
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: