예제 #1
0
  @SubscribeEvent
  public void onLivingUpdateEvent(LivingUpdateEvent event) {
    Entity entity = event.entityLiving;
    World world = entity.worldObj;

    /*
     * The purpose of the function is to manifest sprint particles
     * and adjust slipperiness when entity is moving on block, so check
     * that the conditions are met first.
     */
    if (!isMovingOnGround(entity)) {
      return;
    }

    TEBase TE = getTileEntityAtFeet(entity);
    if (TE != null) {

      ItemStack itemStack = getSurfaceItemStack(TE);

      /* Spawn sprint particles client-side. */

      if (world.isRemote && entity.isSprinting() && !entity.isInWater()) {
        ParticleHelper.spawnTileParticleAt(entity, itemStack);
      }

      /* Adjust block slipperiness according to cover. */

      Block block = BlockProperties.toBlock(itemStack);
      if (block instanceof BlockCoverable) {
        TE.getBlockType().slipperiness = Blocks.dirt.slipperiness;
      } else {
        TE.getBlockType().slipperiness = block.slipperiness;
      }
    }
  }
  @Override
  /** Updates the blocks bounds based on its current state. Args: world, x, y, z */
  public void setBlockBoundsBasedOnState(IBlockAccess blockAccess, int x, int y, int z) {
    if (!rayTracing) {

      TEBase TE = getTileEntity(blockAccess, x, y, z);

      if (TE != null) {

        int slopeID = TE.getData();
        Slope slope = Slope.slopesList[slopeID];

        switch (slope.getPrimaryType()) {
          case PRISM:
          case PRISM_1P:
          case PRISM_2P:
          case PRISM_3P:
          case PRISM_4P:
            if (slope.isPositive) {
              setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5F, 1.0F);
            } else {
              setBlockBounds(0.0F, 0.5F, 0.0F, 1.0F, 1.0F, 1.0F);
            }
            break;
          default:
            setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
            break;
        }
      }
    }
  }
  @Override
  /** Alters block type. */
  protected boolean onHammerRightClick(TEBase TE, EntityPlayer entityPlayer) {
    int slopeID = TE.getData();
    Slope slope = Slope.slopesList[slopeID];

    /* Transform slope to next type. */
    slopeID = slope.slopeType.onHammerRightClick(slope, slopeID);

    TE.setData(slopeID);

    return true;
  }
  @Override
  /** Alters block direction. */
  protected boolean onHammerLeftClick(TEBase TE, EntityPlayer entityPlayer) {
    int slopeID = TE.getData();
    Slope slope = Slope.slopesList[slopeID];

    /* Cycle between slope types based on current slope. */
    slopeID = slope.slopeType.onHammerLeftClick(slope, slopeID);

    TE.setData(slopeID);

    return true;
  }
  @Override
  /** Checks if the block is a solid face on the given side, used by placement logic. */
  public boolean isSideSolid(IBlockAccess blockAccess, int x, int y, int z, ForgeDirection side) {
    TEBase TE = getTileEntity(blockAccess, x, y, z);

    if (TE != null) {
      if (isBlockSolid(blockAccess, x, y, z)) {
        return Slope.slopesList[TE.getData()].isFaceFull(side);
      }
    }

    return false;
  }
예제 #6
0
  /**
   * Gets an {@link ItemStack} that best represents the surface of a Carpenter's Block.
   *
   * <p>The top side cover and any overlays are taken into consideration.
   *
   * @param TE
   * @return
   */
  private ItemStack getSurfaceItemStack(TEBase TE) {
    // Check for top side cover
    int effectiveSide = TE.hasAttribute(TE.ATTR_COVER[1]) ? 1 : 6;
    ItemStack itemStack = BlockProperties.getCover(TE, effectiveSide);

    // Check for overlay on cover
    if (TE.hasAttribute(TE.ATTR_OVERLAY[effectiveSide])) {
      Overlay overlay =
          OverlayHandler.getOverlayType(TE.getAttribute(TE.ATTR_OVERLAY[effectiveSide]));
      if (OverlayHandler.coversFullSide(overlay, 1)) {
        itemStack = overlay.getItemStack();
      }
    }

    return itemStack;
  }
  @Override
  /**
   * Ray traces through the blocks collision from start vector to end vector returning a ray trace
   * hit. Args: world, x, y, z, startVec, endVec
   */
  public MovingObjectPosition collisionRayTrace(
      World world, int x, int y, int z, Vec3 startVec, Vec3 endVec) {
    TEBase TE = getTileEntity(world, x, y, z);
    MovingObjectPosition finalTrace = null;

    if (TE != null) {

      Slope slope = Slope.slopesList[TE.getData()];
      SlopeUtil slopeUtil = new SlopeUtil();

      int numPasses = slopeUtil.getNumPasses(slope);
      int precision = slopeUtil.getNumBoxesPerPass(slope);

      rayTracing = true;

      /* Determine if ray trace is a hit on slope. */
      for (int pass = 0; pass < numPasses; ++pass) {
        for (int slice = 0; slice < precision && finalTrace == null; ++slice) {
          float[] box = slopeUtil.genBounds(slope, slice, precision, pass);

          if (box != null) {
            setBlockBounds(box[0], box[1], box[2], box[3], box[4], box[5]);
            finalTrace = super.collisionRayTrace(world, x, y, z, startVec, endVec);
          }
        }
        if (slope.type.equals(Type.OBLIQUE_EXT)) {
          --precision;
        }
      }

      rayTracing = false;

      /* Determine true face hit since sloped faces are two or more shared faces. */

      if (finalTrace != null) {
        setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        finalTrace = super.collisionRayTrace(world, x, y, z, startVec, endVec);
      }
    }

    return finalTrace;
  }
  @Override
  /** Returns whether sides share faces based on sloping property and face shape. */
  protected boolean shareFaces(
      TEBase TE_adj, TEBase TE_src, ForgeDirection side_adj, ForgeDirection side_src) {
    if (TE_adj.getBlockType() == this) {

      Slope slope_src = Slope.slopesList[TE_src.getData()];
      Slope slope_adj = Slope.slopesList[TE_adj.getData()];

      if (!slope_adj.hasSide(side_adj)) {
        return false;
      } else if (slope_src.getFaceBias(side_src) == slope_adj.getFaceBias(side_adj)) {
        return true;
      } else {
        return false;
      }
    }

    return super.shareFaces(TE_adj, TE_src, side_adj, side_src);
  }
예제 #9
0
  @SideOnly(Side.CLIENT)
  @SubscribeEvent
  public void onPlaySoundEvent(PlaySoundEvent17 event) {
    if (event != null && event.name != null && event.name.contains(CarpentersBlocks.MODID)) {
      if (FMLCommonHandler.instance().getSide() == Side.CLIENT) {
        World world = FMLClientHandler.instance().getClient().theWorld;
        int x = MathHelper.floor_double(event.sound.getXPosF());
        int y = MathHelper.floor_double(event.sound.getYPosF());
        int z = MathHelper.floor_double(event.sound.getZPosF());

        // We'll set a default block type to be safe
        Block block = Blocks.planks;

        // Grab approximate origin, and gather accurate block type
        TEBase TE = getApproximateSoundOrigin(world, x, y, z);
        if (TE != null && TE.hasAttribute(TE.ATTR_COVER[6])) {
          block = BlockProperties.toBlock(BlockProperties.getCoverSafe(TE, 6));
        }

        if (event.name.startsWith("step.")) {
          event.result =
              new PositionedSoundRecord(
                  new ResourceLocation(block.stepSound.getStepResourcePath()),
                  block.stepSound.getVolume() * 0.15F,
                  block.stepSound.getPitch(),
                  x + 0.5F,
                  y + 0.5F,
                  z + 0.5F);
        } else { // "dig." usually
          event.result =
              new PositionedSoundRecord(
                  new ResourceLocation(block.stepSound.getBreakSound()),
                  (block.stepSound.getVolume() + 1.0F) / 2.0F,
                  block.stepSound.getPitch() * 0.8F,
                  x + 0.5F,
                  y + 0.5F,
                  z + 0.5F);
        }
      }
    }
  }
  @Override
  /**
   * Adds all intersecting collision boxes to a list. (Be sure to only add boxes to the list if they
   * intersect the mask.) Parameters: World, X, Y, Z, mask, list, colliding entity
   */
  public void addCollisionBoxesToList(
      World world, int x, int y, int z, AxisAlignedBB axisAlignedBB, List list, Entity entity) {
    TEBase TE = getTileEntity(world, x, y, z);

    if (TE != null) {

      AxisAlignedBB box = null;

      Slope slope = Slope.slopesList[TE.getData()];
      SlopeUtil slopeUtil = new SlopeUtil();

      int precision = slopeUtil.getNumBoxesPerPass(slope);
      int numPasses = slopeUtil.getNumPasses(slope);

      for (int pass = 0; pass < numPasses; ++pass) {

        for (int slice = 0; slice < precision; ++slice) {
          float[] dim = slopeUtil.genBounds(slope, slice, precision, pass);

          if (dim != null) {
            box =
                AxisAlignedBB.getBoundingBox(
                    x + dim[0], y + dim[1], z + dim[2], x + dim[3], y + dim[4], z + dim[5]);
          }

          if (box != null && axisAlignedBB.intersectsWith(box)) {
            list.add(box);
          }
        }

        if (slope.type.equals(Type.OBLIQUE_EXT)) {
          --precision;
        }
      }
    }
  }
  @Override
  public boolean rotateBlock(World world, int x, int y, int z, ForgeDirection axis) {
    // to correctly support archimedes' ships mod:
    // if Axis is DOWN, block rotates to the left, north -> west -> south -> east
    // if Axis is UP, block rotates to the right:  north -> east -> south -> west

    TileEntity tile = world.getTileEntity(x, y, z);
    if (tile != null && tile instanceof TEBase) {
      TEBase cbTile = (TEBase) tile;
      int data = cbTile.getData();
      int dataAngle = data % 4;
      switch (axis) {
        case UP:
          {
            switch (dataAngle) {
              case 0:
                {
                  cbTile.setData(data + 3);
                  break;
                }
              case 1:
                {
                  cbTile.setData(data + 1);
                  break;
                }
              case 2:
                {
                  cbTile.setData(data - 2);
                  break;
                }
              case 3:
                {
                  cbTile.setData(data - 2);
                  break;
                }
            }
            break;
          }
        case DOWN:
          {
            switch (dataAngle) {
              case 0:
                {
                  cbTile.setData(data + 2);
                  break;
                }
              case 1:
                {
                  cbTile.setData(data + 2);
                  break;
                }
              case 2:
                {
                  cbTile.setData(data - 1);
                  break;
                }
              case 3:
                {
                  cbTile.setData(data - 3);
                  break;
                }
            }
            break;
          }
        default:
          return false;
      }
      return true;
    }
    return false;
  }
  @Override
  /**
   * Called when the block is placed in the world. Uses cardinal direction to adjust metadata if
   * player clicks top or bottom face of block.
   */
  public void onBlockPlacedBy(
      World world, int x, int y, int z, EntityLivingBase entityLiving, ItemStack itemStack) {
    TEBase TE = getTileEntity(world, x, y, z);

    if (TE != null) {

      int slopeID = 0;
      int metadata = world.getBlockMetadata(x, y, z);

      boolean isPositive =
          EventHandler.eventFace > 1 && EventHandler.hitY < 0.5F || EventHandler.eventFace == 1;
      int corner = getCorner(entityLiving.rotationYaw);

      ForgeDirection dir = EntityLivingUtil.getFacing(entityLiving).getOpposite();

      switch (metadata) {
        case META_WEDGE:
          slopeID =
              getWedgeOrientation(
                  dir,
                  EventHandler.eventFace,
                  EventHandler.hitX,
                  EventHandler.hitY,
                  EventHandler.hitZ);

          if (!entityLiving.isSneaking()) {
            slopeID = SlopeTransform.transformWedge(world, slopeID, x, y, z);
            TE.setData(slopeID);
            SlopeTransform.transformAdjacentWedges(world, slopeID, x, y, z);
          }

          break;
        case META_OBLIQUE_INT:
          switch (corner) {
            case CORNER_SE:
              slopeID = isPositive ? Slope.ID_OBL_INT_POS_SE : Slope.ID_OBL_INT_NEG_SE;
              break;
            case CORNER_NE:
              slopeID = isPositive ? Slope.ID_OBL_INT_POS_NE : Slope.ID_OBL_INT_NEG_NE;
              break;
            case CORNER_NW:
              slopeID = isPositive ? Slope.ID_OBL_INT_POS_NW : Slope.ID_OBL_INT_NEG_NW;
              break;
            case CORNER_SW:
              slopeID = isPositive ? Slope.ID_OBL_INT_POS_SW : Slope.ID_OBL_INT_NEG_SW;
              break;
          }

          break;
        case META_OBLIQUE_EXT:
          switch (corner) {
            case CORNER_SE:
              slopeID = isPositive ? Slope.ID_OBL_EXT_POS_SE : Slope.ID_OBL_EXT_NEG_SE;
              break;
            case CORNER_NE:
              slopeID = isPositive ? Slope.ID_OBL_EXT_POS_NE : Slope.ID_OBL_EXT_NEG_NE;
              break;
            case CORNER_NW:
              slopeID = isPositive ? Slope.ID_OBL_EXT_POS_NW : Slope.ID_OBL_EXT_NEG_NW;
              break;
            case CORNER_SW:
              slopeID = isPositive ? Slope.ID_OBL_EXT_POS_SW : Slope.ID_OBL_EXT_NEG_SW;
              break;
          }

          break;
        case META_PRISM:
          if (isPositive) {

            slopeID = Slope.ID_PRISM_POS;

            if (!entityLiving.isSneaking()) {
              slopeID = SlopeTransform.transformPrism(world, slopeID, x, y, z);
              TE.setData(slopeID);
              SlopeTransform.transformAdjacentPrisms(world, x, y, z);
            }

          } else {

            slopeID = Slope.ID_PRISM_NEG;
          }

          break;
        case META_PRISM_SLOPE:
          switch (dir) {
            case NORTH:
              slopeID = Slope.ID_PRISM_WEDGE_POS_S;
              break;
            case SOUTH:
              slopeID = Slope.ID_PRISM_WEDGE_POS_N;
              break;
            case WEST:
              slopeID = Slope.ID_PRISM_WEDGE_POS_E;
              break;
            case EAST:
              slopeID = Slope.ID_PRISM_WEDGE_POS_W;
              break;
            default:
              {
              }
          }

          break;
      }

      TE.setData(slopeID);
    }

    super.onBlockPlacedBy(world, x, y, z, entityLiving, itemStack);
  }