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

Method attemptTeleport (used for chorus fruit) sends invalid positions to client

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Resolution: Awaiting Response
    • Affects Version/s: Minecraft 1.10.2
    • Fix Version/s: None
    • Confirmation Status:
      Unconfirmed

      Description

      The following is based on a decompiled version of Minecraft 1.10 using MCP 9.30.

      The bug

      The server sends invalid positions to the client when the method net.minecraft.entity.EntityLivingBase.attemptTeleport(double, double, double) is called. The chorus fruit tries 16 times to teleport the player, the position it creates might be inside the ground, but the server sends this position anyway even if it was canceled.

      Old code
      /**
       * Teleports the entity to the specified location. Used for Enderman and Chorus Fruit teleportation
       */
      public boolean attemptTeleport(double x, double y, double z)
      {
          double d0 = this.posX;
          double d1 = this.posY;
          double d2 = this.posZ;
          this.posX = x;
          this.posY = y;
          this.posZ = z;
          boolean flag = false;
          BlockPos blockpos = new BlockPos(this);
          World world = this.worldObj;
          Random random = this.getRNG();
      
          if (world.isBlockLoaded(blockpos))
          {
              boolean flag1 = false;
      
              while (!flag1 && blockpos.getY() > 0)
              {
                  BlockPos blockpos1 = blockpos.down();
                  IBlockState iblockstate = world.getBlockState(blockpos1);
      
                  if (iblockstate.getMaterial().blocksMovement())
                  {
                      flag1 = true;
                  }
                  else
                  {
                      --this.posY;
                      blockpos = blockpos1;
                  }
              }
      
              if (flag1)
              {
                  // Changes position even if the position might be inside the ground
                  this.setPositionAndUpdate(this.posX, this.posY, this.posZ);
      
                  if (world.getCollisionBoxes(this, this.getEntityBoundingBox()).isEmpty() && !world.containsAnyLiquid(this.getEntityBoundingBox()))
                  {
                      flag = true;
                  }
              }
          }
      
          if (!flag)
          {
              this.setPositionAndUpdate(d0, d1, d2);
              return false;
          }
          else
          {
              int i = 128;
      
              for (int j = 0; j < 128; ++j)
              {
                  double d6 = (double)j / 127.0D;
                  float f = (random.nextFloat() - 0.5F) * 0.2F;
                  float f1 = (random.nextFloat() - 0.5F) * 0.2F;
                  float f2 = (random.nextFloat() - 0.5F) * 0.2F;
                  double d3 = d0 + (this.posX - d0) * d6 + (random.nextDouble() - 0.5D) * (double)this.width * 2.0D;
                  double d4 = d1 + (this.posY - d1) * d6 + random.nextDouble() * (double)this.height;
                  double d5 = d2 + (this.posZ - d2) * d6 + (random.nextDouble() - 0.5D) * (double)this.width * 2.0D;
                  world.spawnParticle(EnumParticleTypes.PORTAL, d3, d4, d5, (double)f, (double)f1, (double)f2, new int[0]);
              }
      
              if (this instanceof EntityCreature)
              {
                  ((EntityCreature)this).getNavigator().clearPathEntity();
              }
      
              return true;
          }
      }
      
      New code
      /**
       * Teleports the entity to the specified location. Used for Enderman and Chorus Fruit teleportation
       */
      public boolean attemptTeleport(double x, double y, double z)
      {
          double oldPosX = this.posX;
          double oldPosY = this.posY;
          double oldPosZ = this.posZ;
          boolean teleportSuccessful = false;
          BlockPos blockpos = new BlockPos(x, y, z);
          World world = this.worldObj;
          Random random = this.getRNG();
      
          if (world.isBlockLoaded(blockpos))
          {
              boolean foundValidBlockToStandOn = false;
      
              while (!foundValidBlockToStandOn && blockpos.getY() > 0)
              {
                  BlockPos blockpos1 = blockpos.down();
                  IBlockState iblockstate = world.getBlockState(blockpos1);
      
                  if (iblockstate.getMaterial().blocksMovement())
                  {
                      foundValidBlockToStandOn = true;
                  }
                  else
                  {
                      --y;
                      blockpos = blockpos1;
                  }
              }
      
              if (foundValidBlockToStandOn)
              {
                  AxisAlignedBB offsetBoundingBox = this.getEntityBoundingBox().offset(x - oldPosX, y - oldPosY, z - oldPosZ);
                  if (world.getCollisionBoxes(this, offsetBoundingBox).isEmpty() && !world.containsAnyLiquid(offsetBoundingBox))
                  {
                      teleportSuccessful = true;
                  }
              }
          }
      
          if (!teleportSuccessful)
          {
              return false;
          }
          else
          {
              this.setPositionAndUpdate(x, y, z);
      
              for (int j = 0; j < 128; ++j)
              {
                  double d6 = (double)j / 127.0D;
                  float f = (random.nextFloat() - 0.5F) * 0.2F;
                  float f1 = (random.nextFloat() - 0.5F) * 0.2F;
                  float f2 = (random.nextFloat() - 0.5F) * 0.2F;
                  double d3 = oldPosX + (this.posX - oldPosX) * d6 + (random.nextDouble() - 0.5D) * (double)this.width * 2.0D;
                  double d4 = oldPosY + (this.posY - oldPosY) * d6 + random.nextDouble() * (double)this.height;
                  double d5 = oldPosZ + (this.posZ - oldPosZ) * d6 + (random.nextDouble() - 0.5D) * (double)this.width * 2.0D;
                  world.spawnParticle(EnumParticleTypes.PORTAL, d3, d4, d5, (double)f, (double)f1, (double)f2, new int[0]);
              }
      
              if (this instanceof EntityCreature)
              {
                  ((EntityCreature)this).getNavigator().clearPathEntity();
              }
      
              return true;
          }
      }
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                jeb [Mojang] Jeb (Jens Bergensten)
                Reporter:
                marcono1234 [Mod] Marcono1234
              • Votes:
                4 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  CHK: