@Override
  public boolean onBlockDestroyed(
      ItemStack stack, World world, Block block, int x, int y, int z, EntityLivingBase entity) {

    if (!(entity instanceof EntityPlayer)) {
      return false;
    }
    EntityPlayer player = (EntityPlayer) entity;

    if (block.getBlockHardness(world, x, y, z) != 0.0D) {
      if (isEmpowered(stack) && canHarvestBlock(block, stack)) {
        Material bMat = world.getBlock(x, y, z).getMaterial();
        Block adjBlock = world.getBlock(x, y - 1, z);
        if (adjBlock != null
            && adjBlock.getMaterial() == bMat
            && adjBlock.getBlockHardness(world, x, y - 1, z) != -1) {
          harvestBlock(world, x, y - 1, z, player);
        }
        adjBlock = world.getBlock(x, y + 1, z);
        if (adjBlock != null
            && adjBlock.getMaterial() == bMat
            && adjBlock.getBlockHardness(world, x, y + 1, z) != -1) {
          harvestBlock(world, x, y + 1, z, player);
        }
      }
      if (!player.capabilities.isCreativeMode) {
        useEnergy(stack, false);
      }
    }
    return true;
  }
  @Override
  public boolean canHarvestBlock(Block block, ItemStack itemStack) {
    ToolMaterial toolMaterial =
        ToolMaterial.values()[itemStack.stackTagCompound.getInteger("material")];

    try {
      if (block.getBlockHardness(null, 0, 0, 0) == -1) {
        return false;
      }
    } catch (NullPointerException e) {
      return false;
    }

    if (block.getMaterial().isToolNotRequired()) {
      return true;
    }

    if (toolMaterial == ToolMaterial.WOOD) {
      return Items.wooden_pickaxe.func_150897_b /*canHarvestBlock*/(block)
          || Items.wooden_shovel.func_150897_b(block);
    } else if (toolMaterial == ToolMaterial.STONE) {
      return Items.stone_pickaxe.func_150897_b(block) || Items.stone_shovel.func_150897_b(block);
    } else if (toolMaterial == ToolMaterial.EMERALD) {
      return Items.diamond_pickaxe.func_150897_b(block)
          || Items.diamond_shovel.func_150897_b(block);
    } else if (toolMaterial == ToolMaterial.IRON) {
      return Items.iron_pickaxe.func_150897_b(block) || Items.iron_shovel.func_150897_b(block);
    } else if (toolMaterial == ToolMaterial.GOLD) {
      return Items.golden_pickaxe.func_150897_b(block) || Items.golden_shovel.func_150897_b(block);
    }

    return toolMaterial.getHarvestLevel() >= block.getHarvestLevel(0);
  }
 /** Returns true if the whip can grapple the block at x/y/z */
 protected boolean canGrabBlock(Block block, int x, int y, int z, int side) {
   if (block instanceof IWhipBlock) {
     return ((IWhipBlock) block).canGrabBlock(getType(), getThrower(), worldObj, x, y, z, side);
   }
   switch (getType()) {
     case WHIP_MAGIC:
       // this excludes things like dirt, most plants, etc.
       if (block instanceof BlockSandStone
           || block instanceof BlockHugeMushroom
           || (block.getMaterial().blocksMovement()
               && block.getBlockHardness(worldObj, x, y, z) > 1.0F)) {
         return true;
       } // otherwise, fall through to standard case:
     case WHIP_SHORT:
     case WHIP_LONG:
       int clear = 0;
       if (isSideClear(x + 1, y, z) && isSideClear(x - 1, y, z)) {
         ++clear;
       }
       if (isSideClear(x, y + 1, z) && isSideClear(x, y - 1, z)) {
         ++clear;
       }
       if (isSideClear(x, y, z + 1) && isSideClear(x, y, z - 1)) {
         ++clear;
       }
       return (clear > 1
           && (block instanceof BlockFence
               || block instanceof BlockLog
               || block instanceof BlockLever
               || block instanceof BlockSign
               || block instanceof BlockLadder));
   }
   return false;
 }
Example #4
0
 @Override
 public boolean onBlockDestroyed(
     ItemStack itemstack, World world, Block block, int x, int y, int z, EntityLivingBase entiy) {
   if (itemstack.hasTagCompound() && itemstack.stackTagCompound.getInteger("Type") == 1) {
     itemstack.damageItem(2, entiy);
   } else {
     if ((double) block.getBlockHardness(world, x, y, z) != 0.0D) {
       itemstack.damageItem(1, entiy);
     }
   }
   return true;
 }
Example #5
0
  @Override
  public boolean onBlockDestroyed(
      ItemStack itemStack,
      World world,
      Block par3,
      int par4,
      int par5,
      int par6,
      EntityLivingBase par7EntityLiving) {
    if ((double) par3.getBlockHardness(world, par4, par5, par6) != 0.0D)
      itemStack.damageItem(2, par7EntityLiving);

    return true;
  }
Example #6
0
  public static boolean canChangeBlock(int blockID, World world, int x, int y, int z) {
    Block block = Block.blocksList[blockID];

    if (blockID == 0 || block == null || block.isAirBlock(world, x, y, z)) return true;

    if (block.getBlockHardness(world, x, y, z) < 0) return false;

    if (blockID == BuildCraftEnergy.oilMoving.blockID
        || blockID == BuildCraftEnergy.oilStill.blockID) return false;

    if (blockID == Block.lavaStill.blockID || blockID == Block.lavaMoving.blockID) return false;

    return true;
  }
Example #7
0
  public static float blockStrength(
      Block block, EntityPlayer player, World world, int x, int y, int z) {
    int metadata = world.getBlockMetadata(x, y, z);
    float hardness = block.getBlockHardness(world, x, y, z);
    if (hardness < 0.0F) {
      return 0.0F;
    }

    if (!canHarvestBlock(block, player, metadata)) {
      float speed = ForgeEventFactory.getBreakSpeed(player, block, metadata, 1.0f);
      return (speed < 0 ? 0 : speed) / hardness / 100F;
    } else {
      return player.getCurrentPlayerStrVsBlock(block, false, metadata) / hardness / 30F;
    }
  }
Example #8
0
  public boolean onBlockDestroyed(
      ItemStack p_150894_1_,
      World p_150894_2_,
      Block p_150894_3_,
      int p_150894_4_,
      int p_150894_5_,
      int p_150894_6_,
      EntityLivingBase p_150894_7_) {
    if ((double) p_150894_3_.getBlockHardness(p_150894_2_, p_150894_4_, p_150894_5_, p_150894_6_)
        != 0.0D) {
      p_150894_1_.damageItem(2, p_150894_7_);
    }

    return true;
  }
 /** Returns true if the whip can destroy the material type */
 protected boolean canBreakBlock(Block block, Material m, int x, int y, int z, int side) {
   EntityLivingBase thrower = getThrower();
   if (block instanceof IWhipBlock) {
     return ((IWhipBlock) block).canBreakBlock(getType(), thrower, worldObj, x, y, z, side);
   }
   boolean isBreakable = block.getBlockHardness(worldObj, x, y, z) >= 0.0F;
   boolean canPlayerEdit = false;
   if (thrower instanceof EntityPlayer) {
     canPlayerEdit =
         ((EntityPlayer) thrower).capabilities.allowEdit && Config.canHookshotBreakBlocks();
   }
   // can dislodge blocks such as torches, leaves, flowers, etc.
   return (isBreakable
       && canPlayerEdit
       && (block instanceof BlockTorch || m == Material.leaves || m == Material.plants));
 }
Example #10
0
  /* Tests a block to see if it can be mined with the current equipment
   * Returns 0 if it can't, -1 if it is cobble
   * Will return 2 if mined with pick, 3 if shovel, 1 if none
   * return 4 if just need to fill using the filler upgrade  */
  public int canMineBlock(int x, int y, int z) {
    BlockPos minePos = new BlockPos(x, y, z);
    IBlockState tryState = worldObj.getBlockState(minePos);
    Block tryBlock = tryState.getBlock();

    if (tryBlock != null) {
      int meta = tryBlock.getMetaFromState(tryState);
      if ((tryBlock.getBlockHardness(tryState, worldObj, minePos) >= 0)
          && (!tryBlock.isAir(tryState, worldObj, minePos))) {
        boolean mine = false;
        // ProgressiveAutomation.logger.info("Tool: "+tryBlock.getHarvestTool(meta)+", Level:
        // "+tryBlock.getHarvestLevel(meta)+", Can use Pick: "+tryBlock.isToolEffective("pickaxe",
        // meta));
        // ProgressiveAutomation.logger.info("Harvestable:
        // "+ForgeHooks.canToolHarvestBlock(tryBlock, meta, getStackInSlot(2)));
        if (tryBlock == Blocks.COBBLESTONE) {
          return -1;
        }
        if (tryBlock.getHarvestTool(tryState) == "chisel") { // this is compatibility for chisel 1
          return 2;
        } else if (tryBlock.getHarvestTool(tryState) == "pickaxe") {
          if (ForgeHooks.canToolHarvestBlock(worldObj, minePos, getStackInSlot(2))) {
            // ProgressiveAutomation.logger.info("Tool can harvest");
            return 2;
          }
        } else if (tryBlock.getHarvestTool(tryState) == "shovel") {
          if (ForgeHooks.canToolHarvestBlock(worldObj, minePos, getStackInSlot(3))) {
            return 3;
          }
        } else {
          if (!tryBlock.getMaterial(tryState).isLiquid()) {
            return 1;
          }
        }
      }

      // see if the filler upgrade is active, if it is then the block will need to be filled.
      if (hasUpgrade(UpgradeType.FILLER)) {
        if ((tryBlock.isAir(tryState, worldObj, minePos))
            || (tryBlock.getMaterial(tryState).isLiquid())) {
          return 4;
        }
      }
    }
    return 0;
  }
  private void breakBlock() {
    if (worldObj.isRemote) return;

    ForgeDirection direction = getRotation();
    int x = xCoord + direction.offsetX,
        y = yCoord + direction.offsetY,
        z = zCoord + direction.offsetZ;

    if (worldObj.blockExists(x, y, z)) {
      int blockId = worldObj.getBlockId(x, y, z);
      Block block = Block.blocksList[blockId];
      if (block != null) {
        int metadata = worldObj.getBlockMetadata(x, y, z);
        if (block != Block.bedrock && block.getBlockHardness(worldObj, z, y, z) > -1.0F) {
          EntityPlayer fakePlayer = OpenModsFakePlayer.getPlayerForWorld(worldObj);
          fakePlayer.inventory.currentItem = 0;
          fakePlayer.inventory.setInventorySlotContents(0, new ItemStack(Item.pickaxeDiamond));
          if (ForgeHooks.canHarvestBlock(block, fakePlayer, metadata)) {
            ArrayList<ItemStack> items = block.getBlockDropped(worldObj, x, y, z, metadata, 0);
            if (items != null) {
              ForgeDirection back = direction.getOpposite();
              ejectAt(
                  worldObj,
                  xCoord + back.offsetX,
                  yCoord + back.offsetY,
                  zCoord + back.offsetZ,
                  back,
                  items);
            }
          }
          fakePlayer.setDead();
          worldObj.playAuxSFX(2001, x, y, z, blockId + (metadata << 12));
          worldObj.setBlockToAir(x, y, z);
        }
      }
      worldObj.playSoundEffect(
          xCoord + 0.5D,
          yCoord + 0.5D,
          zCoord + 0.5D,
          "tile.piston.in",
          0.5F,
          worldObj.rand.nextFloat() * 0.15F + 0.6F);
    }
  }
Example #12
0
  public static List<ItemStack> breakBlock(
      World worldObj,
      EntityPlayer player,
      int x,
      int y,
      int z,
      Block block,
      int fortune,
      boolean doBreak,
      boolean silkTouch) {

    if (block.getBlockHardness(worldObj, x, y, z) == -1) {
      return new LinkedList<ItemStack>();
    }
    int meta = worldObj.getBlockMetadata(x, y, z);
    List<ItemStack> stacks = null;
    if (silkTouch && block.canSilkHarvest(worldObj, player, x, y, z, meta)) {
      stacks = new LinkedList<ItemStack>();
      stacks.add(createStackedBlock(block, meta));
    } else {
      stacks = block.getDrops(worldObj, x, y, z, meta, fortune);
    }
    if (!doBreak) {
      return stacks;
    }
    worldObj.playAuxSFXAtEntity(player, 2001, x, y, z, Block.getIdFromBlock(block) + (meta << 12));
    worldObj.setBlockToAir(x, y, z);

    List<EntityItem> result =
        worldObj.getEntitiesWithinAABB(
            EntityItem.class,
            AxisAlignedBB.getBoundingBox(x - 2, y - 2, z - 2, x + 3, y + 3, z + 3));
    for (int i = 0; i < result.size(); i++) {
      EntityItem entity = result.get(i);
      if (entity.isDead || entity.getEntityItem().stackSize <= 0) {
        continue;
      }
      stacks.add(entity.getEntityItem());
      entity.worldObj.removeEntity(entity);
    }
    return stacks;
  }
 public void grind(World world, int mx, int my, int mz, int x, int y, int z, int meta) {
   if (this.processBlock(world, x, y, z)) {
     if (this.isBedrock(world, x, y, z)) {
       world.playSoundEffect(
           x + 0.5D, y + 0.5D, z + 0.5D, "dig.stone", 0.5F, rand.nextFloat() * 0.4F + 0.8F);
       world.setBlock(x, y, z, BlockRegistry.BEDROCKSLICE.getBlockInstance(), 0, 3);
     } else {
       int rockmetadata = world.getBlockMetadata(x, y, z);
       if (rockmetadata < 15) {
         world.playSoundEffect(
             x + 0.5D, y + 0.5D, z + 0.5D, "dig.stone", 0.5F, rand.nextFloat() * 0.4F + 0.8F);
         world.setBlockMetadataWithNotify(x, y, z, rockmetadata + 1, 3);
       } else {
         world.playSoundEffect(
             x + 0.5D, y + 0.5D, z + 0.5D, "mob.blaze.hit", 0.5F, rand.nextFloat() * 0.4F + 0.8F);
         ItemStack is = this.getDrops(world, x, y, z);
         world.setBlockToAir(x, y, z);
         if (!this.chestCheck(world, x, y, z, is)) {
           if (this.isInventoryFull()) ReikaItemHelper.dropItem(world, dropx, dropy, dropz, is);
           else ReikaInventoryHelper.addOrSetStack(is, inv, 0);
         }
         RotaryAchievements.BEDROCKBREAKER.triggerAchievement(this.getPlacer());
         MinecraftForge.EVENT_BUS.post(new BedrockDigEvent(this, x, y, z));
         if (!world.isRemote) this.incrementStep(world, mx, my, mz);
       }
     }
   } else {
     Block b = world.getBlock(x, y, z);
     if (b != Blocks.air && b.getBlockHardness(world, x, y, z) >= 0) {
       ReikaSoundHelper.playBreakSound(world, x, y, z, b);
       if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT)
         ReikaRenderHelper.spawnDropParticles(world, x, y, z, b, world.getBlockMetadata(x, y, z));
       world.setBlockToAir(x, y, z);
     }
     if (!world.isRemote) this.incrementStep(world, mx, my, mz);
   }
 }
Example #14
0
  @Override
  public int onBlockPlaced(
      World world,
      int int1,
      int int2,
      int int3,
      int int4,
      float float1,
      float float2,
      float float3,
      int int5) {
    if (this == ModBlocks.blockTrytementium) {
      world.createExplosion(null, int1, int2, int3, 10.0F, false);
      for (int i = -9; i <= 9; i++) {
        for (int j = -8; j <= 8; j++) {
          for (int k = -8; k <= 8; k++) {
            Block block = world.getBlock(int1 + i, int2 + j, int3 + k);
            Random rand = new Random();
            int isInfested = rand.nextInt(5);
            int isRemoved = rand.nextInt(2);
            if (block == Blocks.grass
                || block == Blocks.dirt
                || block == ModBlocks.fluxInfestedSoil) {
              if (ConfigurationHandler.trytementiumBoom) {
                block.removedByPlayer(world, null, int1 + i, int2 + j, int3 + k, true);
              }
              if (isInfested <= 1) {
                world.setBlock(int1 + i, int2 + j, int3 + k, ModBlocks.fluxInfestedSoil);
              }
            } else if (block.getBlockHardness(world, int1 + i, int2 + j, int3 + k) != -1
                && ConfigurationHandler.trytementiumBoom) {
              if (isRemoved <= 1 && ConfigurationHandler.trytementiumBoom) {
                block.removedByPlayer(world, null, int1 + i, int2 + j, int3 + k, true);
              }
            }
          }
        }
      }
      for (int i = -8; i <= 8; i++) {
        for (int j = -9; j <= 9; j++) {
          for (int k = -8; k <= 8; k++) {
            Block block = world.getBlock(int1 + i, int2 + j, int3 + k);
            Random rand = new Random();
            int isInfested = rand.nextInt(5);
            int isRemoved = rand.nextInt(2);
            if (block == Blocks.grass
                || block == Blocks.dirt
                || block == ModBlocks.fluxInfestedSoil) {
              if (ConfigurationHandler.trytementiumBoom) {
                block.removedByPlayer(world, null, int1 + i, int2 + j, int3 + k, true);
              }
              if (isInfested <= 1) {
                world.setBlock(int1 + i, int2 + j, int3 + k, ModBlocks.fluxInfestedSoil);
              }
            } else if (block.getBlockHardness(world, int1 + i, int2 + j, int3 + k) != -1
                && ConfigurationHandler.trytementiumBoom) {
              if (isRemoved <= 1 && ConfigurationHandler.trytementiumBoom) {
                block.removedByPlayer(world, null, int1 + i, int2 + j, int3 + k, true);
              }
            }
          }
        }
      }
      for (int i = -8; i <= 8; i++) {
        for (int j = -8; j <= 8; j++) {
          for (int k = -9; k <= 9; k++) {
            Block block = world.getBlock(int1 + i, int2 + j, int3 + k);
            Random rand = new Random();
            int isInfested = rand.nextInt(5);
            int isRemoved = rand.nextInt(2);
            if (block == Blocks.grass
                || block == Blocks.dirt
                || block == ModBlocks.fluxInfestedSoil) {
              block.removedByPlayer(world, null, int1 + i, int2 + j, int3 + k, true);
              if (ConfigurationHandler.trytementiumBoom) {
                block.removedByPlayer(world, null, int1 + i, int2 + j, int3 + k, true);
              }
              if (isInfested <= 1) {
                world.setBlock(int1 + i, int2 + j, int3 + k, ModBlocks.fluxInfestedSoil);
              }

            } else if (block.getBlockHardness(world, int1 + i, int2 + j, int3 + k) != -1
                && ConfigurationHandler.trytementiumBoom) {
              if (isRemoved <= 1 && ConfigurationHandler.trytementiumBoom) {
                block.removedByPlayer(world, null, int1 + i, int2 + j, int3 + k, true);
              }
            }
          }
        }
      }
      world.scheduleBlockUpdate(int1, int2, int3, this, 1);
    }
    return int5;
  }
Example #15
0
  public void mine() {
    if ((slots[1] == null) || (slots[2] == null) || (slots[3] == null)) return;
    if (currentBlock != null) {
      // continue to mine this block
      if (miningTime <= 0) {
        miningTime = 0;
        // clock is done, lets mine it
        Point2I currentPoint = spiral(currentColumn, pos.getX(), pos.getZ());
        BlockPos currentPosition =
            new BlockPos(currentPoint.getX(), currentYLevel, currentPoint.getY());
        // ProgressiveAutomation.logger.info("Point: "+miningWith+"
        // "+currentPoint.getX()+","+currentYLevel+","+currentPoint.getY());

        // don't harvest anything if the block is air or liquid
        if (miningWith != 4) {
          // get the inventory of anything under it
          if (worldObj.getTileEntity(currentPosition) instanceof IInventory) {
            IInventory inv = (IInventory) worldObj.getTileEntity(currentPosition);
            for (int i = 0; i < inv.getSizeInventory(); i++) {
              if (inv.getStackInSlot(i) != null) {
                addToInventory(inv.getStackInSlot(i));
                inv.setInventorySlotContents(i, null);
              }
            }
          }

          // silk touch the block if we have it
          int silkTouch = 0;
          if (miningWith != 1) {
            silkTouch =
                EnchantmentHelper.getEnchantmentLevel(Enchantments.SILK_TOUCH, slots[miningWith]);
          }

          if (silkTouch > 0) {
            int i = 0;
            Item item = Item.getItemFromBlock(currentBlock);
            if (item != null && item.getHasSubtypes())
              i = currentBlock.getMetaFromState(worldObj.getBlockState(currentPosition));

            ItemStack addItem = new ItemStack(currentBlock, 1, i);
            addToInventory(addItem);

          } else {
            // mine the block
            int fortuneLevel = 0;
            if (miningWith != 1) {
              fortuneLevel =
                  EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, slots[miningWith]);
            }

            // then break the block
            List<ItemStack> items =
                currentBlock.getDrops(
                    worldObj,
                    currentPosition,
                    worldObj.getBlockState(currentPosition),
                    fortuneLevel);
            // get the drops
            for (ItemStack item : items) {
              addToInventory(item);
            }
          }

          if (miningWith != 1) {
            if (ToolHelper.damageTool(
                slots[miningWith],
                worldObj,
                currentPoint.getX(),
                currentYLevel,
                currentPoint.getY())) {
              destroyTool(miningWith);
            }
          }
        }

        // remove the block and entity if there is one
        worldObj.removeTileEntity(currentPosition);
        worldObj.setBlockState(currentPosition, Blocks.COBBLESTONE.getDefaultState());
        slots[1].stackSize--;
        if (slots[1].stackSize == 0) {
          slots[1] = null;
        }
        currentMineBlocks++;
        addPartialUpdate("MinedBlocks", currentMineBlocks);
        currentBlock = null;

      } else {
        miningTime--;
      }
    } else {
      if (!isDone()) {
        currentBlock = getNextBlock();
        if (currentBlock != null) {
          Point2I currentPoint = spiral(currentColumn, pos.getX(), pos.getZ());
          BlockPos currentPosition =
              new BlockPos(currentPoint.getX(), currentYLevel, currentPoint.getY());
          IBlockState currentBlockState = worldObj.getBlockState(currentPosition);

          if (miningWith == 4) {
            miningTime = 1;
          } else {
            miningTime =
                (int)
                    Math.ceil(
                        currentBlock.getBlockHardness(currentBlockState, worldObj, currentPosition)
                            * 1.5
                            * 20);

            if (miningWith != 1) {
              float miningSpeed = ToolHelper.getDigSpeed(slots[miningWith], currentBlockState);

              // check for efficiency on the tool
              if (miningSpeed > 1) {
                int eff =
                    EnchantmentHelper.getEnchantmentLevel(
                        Enchantments.EFFICIENCY, slots[miningWith]);
                if (eff > 0) {
                  for (int i = 0; i < eff; i++) {
                    miningSpeed = miningSpeed * 1.3f;
                  }
                }
              }

              miningTime = (int) Math.ceil(miningTime / miningSpeed);
            }
          }

          // ProgressiveAutomation.logger.info("Mining: "+currentBlock.getUnlocalizedName()+" in
          // "+miningTime+" ticks");

        }
      }
    }

    if (isDone()) {
      // ProgressiveAutomation.logger.info("Done Update");
      scanBlocks();
      currentColumn = getRange();
    }
  }
  /**
   * This will check all blocks which are in contact with each other to find the shape of the
   * spacestation. It also finds the centre of mass (to rotate around) and the moment of inertia
   * (how easy/hard this is to rotate).
   *
   * <p>If placingThruster is true, it will return false if the thruster (at baseBlock) is not in
   * contact with the "existing" spacestation - so the player cannot place thrusters on outlying
   * disconnected blocks and expect them to have an effect.
   *
   * <p>Note: this check will briefly load, server-side, all chunks which have spacestation blocks
   * in them or 1 block adjacent to those.
   *
   * @param baseBlock
   * @return
   */
  public boolean checkSS(BlockVec3 baseBlock, boolean placingThruster) {
    if (this.oneSSBlock == null || this.oneSSBlock.getBlockID(this.worldObj) == Blocks.air) {
      if (baseBlock != null) {
        this.oneSSBlock = baseBlock.clone();
      } else {
        this.oneSSBlock = new BlockVec3(0, 64, 0);
      }
    }

    // Find contiguous blocks using an algorithm like the oxygen sealer one
    List<BlockVec3> currentLayer = new LinkedList<BlockVec3>();
    List<BlockVec3> nextLayer = new LinkedList<BlockVec3>();
    final List<BlockVec3> foundThrusters = new LinkedList<BlockVec3>();

    this.checked.clear();
    currentLayer.add(this.oneSSBlock.clone());
    this.checked.add(this.oneSSBlock.clone());
    Block bStart = this.oneSSBlock.getBlockID(this.worldObj);
    if (bStart instanceof BlockSpinThruster) {
      foundThrusters.add(this.oneSSBlock);
    }

    float thismass = 0.1F; // Mass of a thruster
    float thismassCentreX = 0.1F * this.oneSSBlock.x;
    float thismassCentreY = 0.1F * this.oneSSBlock.y;
    float thismassCentreZ = 0.1F * this.oneSSBlock.z;
    float thismoment = 0F;
    int thisssBoundsMaxX = this.oneSSBlock.x;
    int thisssBoundsMinX = this.oneSSBlock.x;
    int thisssBoundsMaxY = this.oneSSBlock.y;
    int thisssBoundsMinY = this.oneSSBlock.y;
    int thisssBoundsMaxZ = this.oneSSBlock.z;
    int thisssBoundsMinZ = this.oneSSBlock.z;

    while (currentLayer.size() > 0) {
      for (BlockVec3 vec : currentLayer) {
        if (vec.x < thisssBoundsMinX) {
          thisssBoundsMinX = vec.x;
        }
        if (vec.y < thisssBoundsMinY) {
          thisssBoundsMinY = vec.y;
        }
        if (vec.z < thisssBoundsMinZ) {
          thisssBoundsMinZ = vec.z;
        }
        if (vec.x > thisssBoundsMaxX) {
          thisssBoundsMaxX = vec.x;
        }
        if (vec.y > thisssBoundsMaxY) {
          thisssBoundsMaxY = vec.y;
        }
        if (vec.z > thisssBoundsMaxZ) {
          thisssBoundsMaxZ = vec.z;
        }

        for (int side = 0; side < 6; side++) {
          if (vec.sideDone[side]) {
            continue;
          }
          BlockVec3 sideVec = vec.newVecSide(side);

          if (!this.checked.contains(sideVec)) {
            this.checked.add(sideVec);
            Block b = sideVec.getBlockID(this.worldObj);
            if (!(b instanceof BlockAir) && b != null) {
              nextLayer.add(sideVec);
              if (bStart == Blocks.air) {
                this.oneSSBlock = sideVec.clone();
                bStart = b;
              }
              float m = 1.0F;
              // Liquids have a mass of 1, stone, metal blocks etc will be heavier
              if (!(b instanceof BlockLiquid)) {
                // For most blocks, hardness gives a good idea of mass
                m = b.getBlockHardness(this.worldObj, sideVec.x, sideVec.y, sideVec.z);
                if (m < 0.1F) {
                  m = 0.1F;
                } else if (m > 30F) {
                  m = 30F;
                }
                // Wood items have a high hardness compared with their presumed mass
                if (b.getMaterial() == Material.wood) {
                  m /= 4;
                }

                // TODO: higher mass for future Galacticraft hi-density item like neutronium
                // Maybe also check for things in other mods by name: lead, uranium blocks?
              }
              thismassCentreX += m * sideVec.x;
              thismassCentreY += m * sideVec.y;
              thismassCentreZ += m * sideVec.z;
              thismass += m;
              thismoment += m * (sideVec.x * sideVec.x + sideVec.z * sideVec.z);
              if (b instanceof BlockSpinThruster) {
                foundThrusters.add(sideVec);
              }
            }
          }
        }
      }

      currentLayer = nextLayer;
      nextLayer = new LinkedList<BlockVec3>();
    }

    if (placingThruster && !this.checked.contains(baseBlock)) {
      if (foundThrusters.size() > 0) {
        // The thruster was not placed on the existing contiguous space station: it must be.
        if (ConfigManagerCore.enableDebug)
          System.out.println(
              "Returning false: oneSSBlock was "
                  + this.oneSSBlock.x
                  + ","
                  + this.oneSSBlock.y
                  + ","
                  + this.oneSSBlock.z
                  + " - baseBlock was "
                  + baseBlock.x
                  + ","
                  + baseBlock.y
                  + ","
                  + baseBlock.z
                  + " - found "
                  + foundThrusters.size());
        return false;
      }

      // No thruster on the original space station - so assume the player made new station and start
      // check again
      // This offers players a reset option: just remove all thrusters from original station then
      // starting adding to new one
      // (This first check prevents an infinite loop)
      if (!this.oneSSBlock.equals(baseBlock)) {
        this.oneSSBlock = baseBlock.clone();
        if (this.oneSSBlock.getBlockID(this.worldObj) != Blocks.air) {
          return this.checkSS(baseBlock, true);
        }
      }

      return false;
    }

    // Update thruster lists based on what was found
    this.thrustersPlus.clear();
    this.thrustersMinus.clear();
    for (BlockVec3 thruster : foundThrusters) {
      int facing = thruster.getBlockMetadata(this.worldObj) & 8;
      if (facing == 0) {
        this.thrustersPlus.add(thruster.clone());
      } else {
        this.thrustersMinus.add(thruster.clone());
      }
    }

    // Calculate centre of mass
    float mass = thismass;

    this.massCentreX = thismassCentreX / thismass + 0.5F;
    float massCentreY = thismassCentreY / thismass + 0.5F;
    this.massCentreZ = thismassCentreZ / thismass + 0.5F;
    // System.out.println("(X,Z) = "+this.massCentreX+","+this.massCentreZ);

    this.setSpinCentre(this.massCentreX, this.massCentreZ);

    // The boundary is at the outer edges of the blocks
    this.ssBoundsMaxX = thisssBoundsMaxX + 1;
    this.ssBoundsMinX = thisssBoundsMinX;
    this.ssBoundsMaxY = thisssBoundsMaxY + 1;
    this.ssBoundsMinY = thisssBoundsMinY;
    this.ssBoundsMaxZ = thisssBoundsMaxZ + 1;
    this.ssBoundsMinZ = thisssBoundsMinZ;

    // Calculate momentOfInertia
    thismoment -= this.massCentreX * this.massCentreX * mass;
    thismoment -= this.massCentreZ * this.massCentreZ * mass;
    this.momentOfInertia = thismoment;

    // TODO
    // TODO defy gravity
    // TODO break blocks which are outside SS (not in checked)
    // TODO prevent spin if there is a huge number of blocks outside SS

    if (ConfigManagerCore.enableDebug)
      System.out.println(
          "MoI = "
              + this.momentOfInertia
              + " CoMx = "
              + this.massCentreX
              + " CoMz = "
              + this.massCentreZ);

    // Send packets to clients in this dimension
    List<Object> objList = new ArrayList<Object>();
    objList.add(Double.valueOf(this.spinCentreX));
    objList.add(Double.valueOf(this.spinCentreZ));
    GalacticraftCore.packetPipeline.sendToDimension(
        new PacketSimple(EnumSimplePacket.C_UPDATE_STATION_DATA, objList),
        this.spaceStationDimensionID);

    objList = new ArrayList<Object>();
    objList.add(Integer.valueOf(this.ssBoundsMinX));
    objList.add(Integer.valueOf(this.ssBoundsMaxX));
    objList.add(Integer.valueOf(this.ssBoundsMinY));
    objList.add(Integer.valueOf(this.ssBoundsMaxY));
    objList.add(Integer.valueOf(this.ssBoundsMinZ));
    objList.add(Integer.valueOf(this.ssBoundsMaxZ));
    GalacticraftCore.packetPipeline.sendToDimension(
        new PacketSimple(EnumSimplePacket.C_UPDATE_STATION_BOX, objList),
        this.spaceStationDimensionID);

    this.updateSpinSpeed();

    return true;
  }
  @Override
  public void doExplode() {
    int r = this.callCount;

    if (!this.world().isRemote && this.thread.isComplete) {
      int blocksToTake = 20;

      for (Vector3 targetPosition : this.thread.results) {
        double distance = targetPosition.add(position).magnitude();

        if (distance > r || distance < r - 2 || blocksToTake <= 0) continue;

        Block block =
            world().getBlock(targetPosition.xi(), targetPosition.yi(), targetPosition.zi());

        if (block == null
            || block.getBlockHardness(
                    world(), targetPosition.xi(), targetPosition.yi(), targetPosition.zi())
                < 0) continue;

        // if (block instanceof IForceFieldBlock)
        //    continue;

        int metadata =
            world().getBlockMetadata(targetPosition.xi(), targetPosition.yi(), targetPosition.zi());

        if (distance < r - 1 || world().rand.nextInt(3) > 0) {
          this.world().setBlockToAir(targetPosition.xi(), targetPosition.yi(), targetPosition.zi());

          targetPosition.add(0.5D);

          if (world().rand.nextFloat() < 0.3 * (this.getRadius() - r)) {
            EntityFlyingBlock entity =
                new EntityFlyingBlock(world(), targetPosition, block, metadata, 0);
            world().spawnEntityInWorld(entity);
            flyingBlocks.add(entity);
            entity.yawChange = 50 * world().rand.nextFloat();
            entity.pitchChange = 100 * world().rand.nextFloat();
            entity.motionY += Math.max(0.15 * world().rand.nextFloat(), 0.1);
          }

          blocksToTake--;
        }
      }
    }

    int radius = (int) this.getRadius();
    AxisAlignedBB bounds =
        AxisAlignedBB.getBoundingBox(
            position.xi() - radius,
            position.yi() - radius,
            position.zi() - radius,
            position.xi() + radius,
            100,
            position.zi() + radius);
    List<Entity> allEntities = world().getEntitiesWithinAABB(Entity.class, bounds);

    for (Entity entity : allEntities) {
      if (!(entity instanceof EntityFlyingBlock) && entity.posY < 100 + position.yi()) {
        if (entity.motionY < 0.4) {
          entity.motionY += 0.15;
        }
      }
    }

    if (this.callCount > 20 * 120) {
      this.controller.endExplosion();
    }
  }