buildcraft/common/buildcraft/core/lib/utils/BlockUtils.java
2017-02-10 00:38:09 +01:00

397 lines
12 KiB
Java

/**
* Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
* <p/>
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.core.lib.utils;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.BlockStaticLiquid;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.network.play.server.S27PacketExplosion;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.world.ChunkPosition;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.world.BlockEvent.BreakEvent;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidBlock;
import buildcraft.BuildCraftCore;
import buildcraft.api.blueprints.BuilderAPI;
import buildcraft.core.proxy.CoreProxy;
public final class BlockUtils {
/**
* Deactivate constructor
*/
private BlockUtils() {
}
public static List<ItemStack> getItemStackFromBlock(WorldServer world, int i, int j, int k) {
Block block = world.getBlock(i, j, k);
if (block == null || block.isAir(world, i, j, k)) {
return null;
}
int meta = world.getBlockMetadata(i, j, k);
ArrayList<ItemStack> dropsList = block.getDrops(world, i, j, k, meta, 0);
float dropChance = ForgeEventFactory.fireBlockHarvesting(dropsList, world, block, i, j, k, meta, 0, 1.0F,
false, CoreProxy.proxy.getBuildCraftPlayer(world).get());
ArrayList<ItemStack> returnList = new ArrayList<ItemStack>();
for (ItemStack s : dropsList) {
if (world.rand.nextFloat() <= dropChance) {
returnList.add(s);
}
}
return returnList;
}
public static boolean breakBlock(WorldServer world, int x, int y, int z) {
return breakBlock(world, x, y, z, BuildCraftCore.itemLifespan * 20);
}
public static boolean breakBlock(WorldServer world, int x, int y, int z, int forcedLifespan) {
List<ItemStack> items = new ArrayList<ItemStack>();
if (breakBlock(world, x, y, z, items)) {
for (ItemStack item : items) {
dropItem(world, x, y, z, forcedLifespan, item);
}
return true;
}
return false;
}
public static EntityPlayer getFakePlayerWithTool(WorldServer world, int x, int y, int z, ItemStack tool) {
EntityPlayer player = CoreProxy.proxy.getBuildCraftPlayer(world, x, y, z).get();
int i = 0;
while (player.getHeldItem() != tool && i < 9) {
if (i > 0) {
player.inventory.setInventorySlotContents(i - 1, null);
}
player.inventory.setInventorySlotContents(i, tool);
i++;
}
return player;
}
public static boolean harvestBlock(WorldServer world, int x, int y, int z, ItemStack tool) {
Block block = world.getBlock(x, y, z);
int meta = world.getBlockMetadata(x, y, z);
EntityPlayer player = getFakePlayerWithTool(world, x, y, z, tool);
BreakEvent breakEvent = new BreakEvent(x, y, z, world, world.getBlock(x, y, z), world.getBlockMetadata(x, y, z), player);
MinecraftForge.EVENT_BUS.post(breakEvent);
if (breakEvent.isCanceled()) {
return false;
}
if (!block.canHarvestBlock(player, meta)) {
return false;
}
if (tool != null && tool.getItem() != null && tool.getItem().onBlockStartBreak(tool, x, y, z, player)) {
return false;
}
block.onBlockHarvested(world, x, y, z, meta, player);
block.harvestBlock(world, player, x, y, z, meta);
world.setBlockToAir(x, y, z);
return true;
}
public static boolean breakBlock(WorldServer world, int x, int y, int z, List<ItemStack> drops) {
BreakEvent breakEvent = new BreakEvent(x, y, z, world, world.getBlock(x, y, z),
world.getBlockMetadata(x, y, z), CoreProxy.proxy.getBuildCraftPlayer(world).get());
MinecraftForge.EVENT_BUS.post(breakEvent);
if (breakEvent.isCanceled()) {
return false;
}
if (!world.isAirBlock(x, y, z) && !world.isRemote
&& world.getGameRules().getGameRuleBooleanValue("doTileDrops")) {
drops.addAll(getItemStackFromBlock(world, x, y, z));
}
world.setBlockToAir(x, y, z);
return true;
}
public static void dropItem(WorldServer world, int x, int y, int z, int forcedLifespan, ItemStack stack) {
float var = 0.7F;
double dx = world.rand.nextFloat() * var + (1.0F - var) * 0.5D;
double dy = world.rand.nextFloat() * var + (1.0F - var) * 0.5D;
double dz = world.rand.nextFloat() * var + (1.0F - var) * 0.5D;
EntityItem entityitem = new EntityItem(world, x + dx, y + dy, z + dz, stack);
entityitem.lifespan = forcedLifespan;
entityitem.delayBeforeCanPickup = 10;
world.spawnEntityInWorld(entityitem);
}
public static boolean canChangeBlock(World world, int x, int y, int z) {
return canChangeBlock(world.getBlock(x, y, z), world, x, y, z);
}
public static boolean canChangeBlock(Block block, World world, int x, int y, int z) {
if (block == null || block.isAir(world, x, y, z)) {
return true;
}
if (isUnbreakableBlock(world, x, y, z, block)) {
return false;
}
if (block == Blocks.lava || block == Blocks.flowing_lava) {
return false;
} else if (block instanceof IFluidBlock && ((IFluidBlock) block).getFluid() != null) {
Fluid f = ((IFluidBlock) block).getFluid();
if (f.getDensity(world, x, y, z) >= 3000) {
return false;
}
}
return true;
}
public static float getBlockHardnessMining(World world, int x, int y, int z, Block b, ItemStack tool) {
if (world instanceof WorldServer && !BuildCraftCore.miningAllowPlayerProtectedBlocks) {
float relativeHardness = b.getPlayerRelativeBlockHardness(getFakePlayerWithTool((WorldServer) world, x, y, z, tool), world, x, y, z);
if (relativeHardness <= 0.0F) { // Forge's getPlayerRelativeBlockHardness hook returns 0.0F if the hardness is < 0.0F.
return -1.0F;
}
}
return b.getBlockHardness(world, x, y, z);
}
public static boolean isUnbreakableBlock(World world, int x, int y, int z, Block b) {
if (b == null) {
return false;
}
return getBlockHardnessMining(world, x, y, z, b, null) < 0;
}
public static boolean isUnbreakableBlock(World world, int x, int y, int z) {
return isUnbreakableBlock(world, x, y, z, world.getBlock(x, y, z));
}
/**
* Returns true if a block cannot be harvested without a tool.
*/
public static boolean isToughBlock(World world, int x, int y, int z) {
return !world.getBlock(x, y, z).getMaterial().isToolNotRequired();
}
public static boolean isFullFluidBlock(World world, int x, int y, int z) {
return isFullFluidBlock(world.getBlock(x, y, z), world, x, y, z);
}
public static boolean isFullFluidBlock(Block block, World world, int x, int y, int z) {
if (block instanceof IFluidBlock) {
return ((IFluidBlock) block).getFilledPercentage(world, x, y, z) == 1.0f;
} else if (block instanceof BlockStaticLiquid) {
return world.getBlockMetadata(x, y, z) == 0;
}
return false;
}
public static Fluid getFluid(Block block) {
if (block instanceof IFluidBlock) {
return ((IFluidBlock) block).getFluid();
} else {
return FluidRegistry.lookupFluidForBlock(block);
}
}
public static FluidStack drainBlock(World world, int x, int y, int z, boolean doDrain) {
return drainBlock(world.getBlock(x, y, z), world, x, y, z, doDrain);
}
public static FluidStack drainBlock(Block block, World world, int x, int y, int z, boolean doDrain) {
if (block instanceof IFluidBlock) {
IFluidBlock fluidBlock = (IFluidBlock) block;
if (!fluidBlock.canDrain(world, x, y, z)) {
return null;
}
return fluidBlock.drain(world, x, y, z, doDrain);
} else {
Fluid fluid = getFluid(block);
if (fluid != null && FluidRegistry.isFluidRegistered(fluid)) {
int meta = world.getBlockMetadata(x, y, z);
if (meta != 0) {
return null;
}
if (doDrain) {
world.setBlockToAir(x, y, z);
}
return new FluidStack(fluid, FluidContainerRegistry.BUCKET_VOLUME);
} else {
return null;
}
}
}
/**
* Create an explosion which only affects a single block.
*/
@SuppressWarnings("unchecked")
public static void explodeBlock(World world, int x, int y, int z) {
if (FMLCommonHandler.instance().getEffectiveSide().isClient()) {
return;
}
Explosion explosion = new Explosion(world, null, x + .5, y + .5, z + .5, 3f);
explosion.affectedBlockPositions.add(new ChunkPosition(x, y, z));
explosion.doExplosionB(true);
for (EntityPlayer player : (List<EntityPlayer>) world.playerEntities) {
if (!(player instanceof EntityPlayerMP)) {
continue;
}
if (player.getDistanceSq(x, y, z) < 4096) {
((EntityPlayerMP) player).playerNetServerHandler.sendPacket(new S27PacketExplosion(x + .5, y + .5, z + .5, 3f, explosion.affectedBlockPositions, null));
}
}
}
public static int computeBlockBreakEnergy(World world, int x, int y, int z) {
return (int) Math.floor(BuilderAPI.BREAK_ENERGY * BuildCraftCore.miningMultiplier * ((world.getBlock(x, y, z).getBlockHardness(world, x, y, z) + 1) * 2));
}
/**
* The following functions let you avoid unnecessary chunk loads, which is nice.
*/
public static TileEntity getTileEntity(World world, int x, int y, int z) {
return getTileEntity(world, x, y, z, false);
}
public static TileEntity getTileEntity(World world, int x, int y, int z, boolean force) {
if (!force) {
if (y < 0 || y > 255) {
return null;
}
Chunk chunk = ThreadSafeUtils.getChunk(world, x >> 4, z >> 4);
return chunk != null ? chunk.getTileEntityUnsafe(x & 15, y, z & 15) : null;
} else {
return world.getTileEntity(x, y, z);
}
}
public static Block getBlock(World world, int x, int y, int z) {
return getBlock(world, x, y, z, false);
}
public static Block getBlock(World world, int x, int y, int z, boolean force) {
if (!force) {
if (y < 0 || y > 255) {
return Blocks.air;
}
Chunk chunk = ThreadSafeUtils.getChunk(world, x >> 4, z >> 4);
return chunk != null ? chunk.getBlock(x & 15, y, z & 15) : Blocks.air;
} else {
return world.getBlock(x, y, z);
}
}
public static int getBlockMetadata(World world, int x, int y, int z) {
return getBlockMetadata(world, x, y, z, false);
}
public static int getBlockMetadata(World world, int x, int y, int z, boolean force) {
if (!force) {
if (y < 0 || y > 255) {
return 0;
}
Chunk chunk = ThreadSafeUtils.getChunk(world, x >> 4, z >> 4);
return chunk != null ? chunk.getBlockMetadata(x & 15, y, z & 15) : 0;
} else {
return world.getBlockMetadata(x, y, z);
}
}
public static boolean useItemOnBlock(World world, EntityPlayer player, ItemStack stack, int x,
int y, int z, ForgeDirection direction) {
boolean done = stack.getItem().onItemUseFirst(stack, player, world, x, y, z,
direction.ordinal(), 0.5F, 0.5F, 0.5F);
if (!done) {
done = stack.getItem().onItemUse(stack, player, world, x, y, z, direction.ordinal(),
0.5F, 0.5F, 0.5F);
}
return done;
}
public static void onComparatorUpdate(World world, int x, int y, int z, Block block) {
world.func_147453_f(x, y, z, block);
}
public static TileEntityChest getOtherDoubleChest(TileEntity inv) {
if (inv instanceof TileEntityChest) {
TileEntityChest chest = (TileEntityChest) inv;
TileEntityChest adjacent = null;
if (chest.adjacentChestXNeg != null) {
adjacent = chest.adjacentChestXNeg;
}
if (chest.adjacentChestXPos != null) {
adjacent = chest.adjacentChestXPos;
}
if (chest.adjacentChestZNeg != null) {
adjacent = chest.adjacentChestZNeg;
}
if (chest.adjacentChestZPos != null) {
adjacent = chest.adjacentChestZPos;
}
return adjacent;
}
return null;
}
}