From 496e6b4ccb000604d5e917bdb44e544232579507 Mon Sep 17 00:00:00 2001 From: asiekierka Date: Thu, 27 Nov 2014 17:21:42 +0100 Subject: [PATCH] quarries run slower in rain; add dynamic break energy for mining wells and quarries; add build energy requirement for placing mining pipes --- common/buildcraft/BuildCraftFactory.java | 1 - common/buildcraft/core/TileBuildCraft.java | 6 +- .../core/blueprints/BptBuilderBase.java | 23 +-- .../core/network/ISynchronizedTile.java | 1 - common/buildcraft/core/utils/BlockUtils.java | 6 + common/buildcraft/factory/BlockMiner.java | 125 ++++++++++++++ common/buildcraft/factory/TileMiningWell.java | 98 ++++------- common/buildcraft/factory/TileQuarry.java | 159 +++++++----------- 8 files changed, 236 insertions(+), 183 deletions(-) create mode 100644 common/buildcraft/factory/BlockMiner.java diff --git a/common/buildcraft/BuildCraftFactory.java b/common/buildcraft/BuildCraftFactory.java index dc2567db..70a2d1c7 100644 --- a/common/buildcraft/BuildCraftFactory.java +++ b/common/buildcraft/BuildCraftFactory.java @@ -74,7 +74,6 @@ public class BuildCraftFactory extends BuildCraftMod { @Mod.Instance("BuildCraft|Factory") public static BuildCraftFactory instance; - public static final int MINING_RF_COST_PER_BLOCK = 640; public static BlockQuarry quarryBlock; public static BlockMiningWell miningWellBlock; public static BlockAutoWorkbench autoWorkbenchBlock; diff --git a/common/buildcraft/core/TileBuildCraft.java b/common/buildcraft/core/TileBuildCraft.java index 6299127a..e439fca3 100644 --- a/common/buildcraft/core/TileBuildCraft.java +++ b/common/buildcraft/core/TileBuildCraft.java @@ -105,13 +105,9 @@ public abstract class TileBuildCraft extends TileEntity implements IEnergyReceiv return new PacketTileUpdate(this); } - public BuildCraftPacket getPacketDescription() { - return getPacketUpdate(); - } - @Override public Packet getDescriptionPacket() { - return Utils.toPacket(getPacketDescription(), 0); + return Utils.toPacket(getPacketUpdate(), 0); } @Override diff --git a/common/buildcraft/core/blueprints/BptBuilderBase.java b/common/buildcraft/core/blueprints/BptBuilderBase.java index 16bd53c7..12c34065 100644 --- a/common/buildcraft/core/blueprints/BptBuilderBase.java +++ b/common/buildcraft/core/blueprints/BptBuilderBase.java @@ -35,6 +35,7 @@ import buildcraft.core.builders.BuildingSlot; import buildcraft.core.builders.BuildingSlotBlock; import buildcraft.core.builders.IBuildingItemsProvider; import buildcraft.core.builders.TileAbstractBuilder; +import buildcraft.core.utils.BlockUtils; public abstract class BptBuilderBase implements IAreaProvider { @@ -181,34 +182,22 @@ public abstract class BptBuilderBase implements IAreaProvider { return done && builder.getBuilders().size() == 0; } - private int getHardness(BuildingSlotBlock slot) { - int hardness = (int) context - .world() - .getBlock(slot.x, slot.y, slot.z) - .getBlockHardness(context.world(), slot.x, slot.y, - slot.z) + 1; - - hardness *= 2; - - return hardness; + private int getBlockBreakEnergy(BuildingSlotBlock slot) { + return BlockUtils.computeBlockBreakEnergy(context.world(), slot.x, slot.y, slot.z); } protected final boolean canDestroy(TileAbstractBuilder builder, IBuilderContext context, BuildingSlotBlock slot) { LinkedList result = new LinkedList(); - int hardness = getHardness(slot); - - return builder.energyAvailable() >= hardness * BuilderAPI.BREAK_ENERGY; + return builder.energyAvailable() >= getBlockBreakEnergy(slot); } public void consumeEnergyToDestroy(TileAbstractBuilder builder, BuildingSlotBlock slot) { - int hardness = getHardness(slot); - - builder.consumeEnergy(hardness * BuilderAPI.BREAK_ENERGY); + builder.consumeEnergy(getBlockBreakEnergy(slot)); } public void createDestroyItems(BuildingSlotBlock slot) { - int hardness = getHardness(slot); + int hardness = (int) Math.ceil(getBlockBreakEnergy(slot) / BuilderAPI.BREAK_ENERGY); for (int i = 0; i < hardness; ++i) { slot.addStackConsumed(new ItemStack(BuildCraftBuilders.buildToolBlock)); diff --git a/common/buildcraft/core/network/ISynchronizedTile.java b/common/buildcraft/core/network/ISynchronizedTile.java index a0e10819..14d14e8a 100644 --- a/common/buildcraft/core/network/ISynchronizedTile.java +++ b/common/buildcraft/core/network/ISynchronizedTile.java @@ -10,5 +10,4 @@ package buildcraft.core.network; public interface ISynchronizedTile { BuildCraftPacket getPacketUpdate(); - BuildCraftPacket getPacketDescription(); } diff --git a/common/buildcraft/core/utils/BlockUtils.java b/common/buildcraft/core/utils/BlockUtils.java index 187c2f60..f0ed1436 100644 --- a/common/buildcraft/core/utils/BlockUtils.java +++ b/common/buildcraft/core/utils/BlockUtils.java @@ -37,6 +37,8 @@ import net.minecraftforge.fluids.IFluidBlock; import buildcraft.BuildCraftCore; import buildcraft.BuildCraftEnergy; +import buildcraft.BuildCraftFactory; +import buildcraft.api.blueprints.BuilderAPI; import buildcraft.core.proxy.CoreProxy; public final class BlockUtils { @@ -215,4 +217,8 @@ public final class BlockUtils { } } } + + public static int computeBlockBreakEnergy(World world, int x, int y, int z) { + return (int) Math.floor(BuilderAPI.BREAK_ENERGY * BuildCraftFactory.miningMultiplier * ((world.getBlock(x, y, z).getBlockHardness(world, x, y, z) + 1) * 2)); + } } diff --git a/common/buildcraft/factory/BlockMiner.java b/common/buildcraft/factory/BlockMiner.java new file mode 100644 index 00000000..8e93bbb8 --- /dev/null +++ b/common/buildcraft/factory/BlockMiner.java @@ -0,0 +1,125 @@ +package buildcraft.factory; + +import java.util.List; +import net.minecraft.block.Block; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.event.world.BlockEvent; +import buildcraft.BuildCraftCore; +import buildcraft.core.proxy.CoreProxy; +import buildcraft.core.utils.BlockUtils; +import buildcraft.core.utils.MathUtils; +import buildcraft.core.utils.Utils; + +public class BlockMiner { + protected final World world; + protected final TileEntity owner; + protected final int x, y, z, minerId; + + private boolean hasMined, hasFailed; + private int energyRequired, energyAccepted; + + public BlockMiner(World world, TileEntity owner, int x, int y, int z) { + this.world = world; + this.owner = owner; + this.x = x; + this.y = y; + this.z = z; + this.minerId = world.rand.nextInt(); + } + + public boolean hasMined() { + return hasMined; + } + + public boolean hasFailed() { + return hasFailed; + } + + public void mineStack(ItemStack stack) { + // First, try to add to a nearby chest + stack.stackSize -= Utils.addToRandomInventoryAround(owner.getWorldObj(), owner.xCoord, owner.yCoord, owner.zCoord, stack); + + // Second, try to add to adjacent pipes + if (stack.stackSize > 0) { + stack.stackSize -= Utils.addToRandomPipeAround(owner.getWorldObj(), owner.xCoord, owner.yCoord, owner.zCoord, ForgeDirection.UNKNOWN, stack); + } + + // Lastly, throw the object away + if (stack.stackSize > 0) { + float f = world.rand.nextFloat() * 0.8F + 0.1F; + float f1 = world.rand.nextFloat() * 0.8F + 0.1F; + float f2 = world.rand.nextFloat() * 0.8F + 0.1F; + + EntityItem entityitem = new EntityItem(owner.getWorldObj(), owner.xCoord + f, owner.yCoord + f1 + 0.5F, owner.zCoord + f2, stack); + + entityitem.lifespan = BuildCraftCore.itemLifespan; + entityitem.delayBeforeCanPickup = 10; + + float f3 = 0.05F; + entityitem.motionX = (float) world.rand.nextGaussian() * f3; + entityitem.motionY = (float) world.rand.nextGaussian() * f3 + 1.0F; + entityitem.motionZ = (float) world.rand.nextGaussian() * f3; + owner.getWorldObj().spawnEntityInWorld(entityitem); + } + } + + public void invalidate() { + world.destroyBlockInWorldPartially(minerId, x, y, z, -1); + } + + public int acceptEnergy(int offeredAmount) { + energyRequired = BlockUtils.computeBlockBreakEnergy(world, x, y, z); + + int usedAmount = MathUtils.clamp(offeredAmount, 0, Math.max(0, energyRequired - energyAccepted)); + energyAccepted += usedAmount; + + if (energyAccepted >= energyRequired) { + world.destroyBlockInWorldPartially(minerId, x, y, z, -1); + + hasMined = true; + + Block block = world.getBlock(x, y, z); + int meta = world.getBlockMetadata(x, y, z); + + BlockEvent.BreakEvent breakEvent = new BlockEvent.BreakEvent(x, y, z, world, block, meta, + CoreProxy.proxy.getBuildCraftPlayer((WorldServer) world).get()); + MinecraftForge.EVENT_BUS.post(breakEvent); + + if (!breakEvent.isCanceled()) { + List stacks = BlockUtils.getItemStackFromBlock((WorldServer) world, x, y, z); + + if (stacks != null) { + for (ItemStack s : stacks) { + if (s != null) { + mineStack(s); + } + } + } + + world.playAuxSFXAtEntity( + null, + 2001, + x, y, z, + Block.getIdFromBlock(block) + + (meta << 12)); + + if (block.hasTileEntity(meta)) { + world.removeTileEntity(x, y, z); + } + + world.setBlockToAir(x, y, z); + } else { + hasFailed = true; + } + } else { + world.destroyBlockInWorldPartially(minerId, x, y, z, MathUtils.clamp((int) Math.floor(energyAccepted * 10 / energyRequired), 0, 9)); + } + return usedAmount; + } +} diff --git a/common/buildcraft/factory/TileMiningWell.java b/common/buildcraft/factory/TileMiningWell.java index b53e35eb..16eb60de 100644 --- a/common/buildcraft/factory/TileMiningWell.java +++ b/common/buildcraft/factory/TileMiningWell.java @@ -19,6 +19,7 @@ import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.event.world.BlockEvent.BreakEvent; import buildcraft.BuildCraftCore; import buildcraft.BuildCraftFactory; +import buildcraft.api.blueprints.BuilderAPI; import buildcraft.api.tiles.IHasWork; import buildcraft.api.transport.IPipeConnection; import buildcraft.api.transport.IPipeTile.PipeType; @@ -29,12 +30,12 @@ import buildcraft.core.utils.BlockUtils; import buildcraft.core.utils.Utils; public class TileMiningWell extends TileBuildCraft implements IHasWork, IPipeConnection { - boolean isDigging = true; + private BlockMiner miner; public TileMiningWell() { super(); - this.setBattery(new RFBattery(10000, BuildCraftFactory.MINING_RF_COST_PER_BLOCK, 0)); + this.setBattery(new RFBattery(2 * 64 * BuilderAPI.BREAK_ENERGY, BuilderAPI.BREAK_ENERGY, 0)); } /** @@ -47,84 +48,53 @@ public class TileMiningWell extends TileBuildCraft implements IHasWork, IPipeCon return; } - int miningCost = (int) Math.ceil(BuildCraftFactory.MINING_RF_COST_PER_BLOCK - * BuildCraftFactory.miningMultiplier); - - if (getBattery().useEnergy(miningCost, miningCost, false) == 0) { + if (getBattery().getEnergyStored() == 0) { return; } - World world = worldObj; + if (miner == null) { + World world = worldObj; - int depth = yCoord - 1; + int depth = yCoord - 1; - while (world.getBlock(xCoord, depth, zCoord) == BuildCraftFactory.plainPipeBlock) { - depth = depth - 1; - } - - if (depth < 1 || depth < yCoord - BuildCraftFactory.miningDepth || !BlockUtils.canChangeBlock(world, xCoord, depth, zCoord)) { - isDigging = false; - return; - } - - BreakEvent breakEvent = new BreakEvent(xCoord, depth, zCoord, worldObj, world.getBlock(xCoord, depth, zCoord), - world.getBlockMetadata(xCoord, depth, zCoord), CoreProxy.proxy.getBuildCraftPlayer((WorldServer) world).get()); - MinecraftForge.EVENT_BUS.post(breakEvent); - - if (breakEvent.isCanceled()) { - isDigging = false; - return; - } - - boolean wasAir = world.isAirBlock(xCoord, depth, zCoord); - - List stacks = BlockUtils.getItemStackFromBlock((WorldServer) worldObj, xCoord, depth, zCoord); - - world.setBlock(xCoord, depth, zCoord, BuildCraftFactory.plainPipeBlock); - - if (wasAir) { - return; - } - - if (stacks == null || stacks.isEmpty()) { - return; - } - - for (ItemStack stack : stacks) { - - stack.stackSize -= Utils.addToRandomInventoryAround(worldObj, xCoord, yCoord, zCoord, stack); - if (stack.stackSize <= 0) { - continue; + while (world.getBlock(xCoord, depth, zCoord) == BuildCraftFactory.plainPipeBlock) { + depth = depth - 1; } - stack.stackSize -= Utils.addToRandomPipeAround(worldObj, xCoord, yCoord, zCoord, ForgeDirection.UNKNOWN, stack); - if (stack.stackSize <= 0) { - continue; + if (depth < 1 || depth < yCoord - BuildCraftFactory.miningDepth || !BlockUtils.canChangeBlock(world, xCoord, depth, zCoord)) { + isDigging = false; + // Drain energy, because at 0 energy this will stop doing calculations. + getBattery().useEnergy(0, 10, false); + return; } - // Throw the object away. - // TODO: factorize that code + if (world.isAirBlock(xCoord, depth, zCoord)) { + if (getBattery().getEnergyStored() >= BuilderAPI.BUILD_ENERGY) { + getBattery().useEnergy(BuilderAPI.BUILD_ENERGY, BuilderAPI.BUILD_ENERGY, false); + world.setBlock(xCoord, depth, zCoord, BuildCraftFactory.plainPipeBlock); + } + } else { + miner = new BlockMiner(world, this, xCoord, depth, zCoord); + } + } else { + int usedEnergy = miner.acceptEnergy(getBattery().getEnergyStored()); + getBattery().useEnergy(usedEnergy, usedEnergy, false); - float f = world.rand.nextFloat() * 0.8F + 0.1F; - float f1 = world.rand.nextFloat() * 0.8F + 0.1F; - float f2 = world.rand.nextFloat() * 0.8F + 0.1F; - - EntityItem entityitem = new EntityItem(world, xCoord + f, yCoord + f1 + 0.5F, zCoord + f2, stack); - - entityitem.lifespan = BuildCraftCore.itemLifespan; - entityitem.delayBeforeCanPickup = 10; - - float f3 = 0.05F; - entityitem.motionX = (float) world.rand.nextGaussian() * f3; - entityitem.motionY = (float) world.rand.nextGaussian() * f3 + 1.0F; - entityitem.motionZ = (float) world.rand.nextGaussian() * f3; - world.spawnEntityInWorld(entityitem); + if (miner.hasMined()) { + if (miner.hasFailed()) { + isDigging = false; + } + miner = null; + } } } @Override public void invalidate() { super.invalidate(); + if (miner != null) { + miner.invalidate(); + } if (worldObj != null && yCoord > 2) { BuildCraftFactory.miningWellBlock.removePipes(worldObj, xCoord, yCoord, zCoord); } diff --git a/common/buildcraft/factory/TileQuarry.java b/common/buildcraft/factory/TileQuarry.java index 51330d69..b85f537e 100644 --- a/common/buildcraft/factory/TileQuarry.java +++ b/common/buildcraft/factory/TileQuarry.java @@ -57,6 +57,7 @@ public class TileQuarry extends TileAbstractBuilder implements IHasWork, ISidedI private static enum Stage { BUILDING, DIGGING, + MOVING, IDLE, DONE } @@ -87,6 +88,8 @@ public class TileQuarry extends TileAbstractBuilder implements IHasWork, ISidedI private NBTTagCompound initNBT = null; + private BlockMiner miner; + public TileQuarry () { box.kind = Kind.STRIPES; } @@ -161,13 +164,26 @@ public class TileQuarry extends TileAbstractBuilder implements IHasWork, ISidedI } else { stage = Stage.IDLE; } - } else if (stage == Stage.IDLE) { - dig(); } else if (stage == Stage.DIGGING) { + dig(); + } else if (stage == Stage.IDLE) { + idling(); + } else if (stage == Stage.MOVING) { int energyToUse = 20 + (int) Math.ceil(getBattery().getEnergyStored() / 500); if (this.consumeEnergy(energyToUse)) { speed = 0.1 + energyToUse / 2000F; + + // If it's raining or snowing above the head, slow down. + if (worldObj.isRaining()) { + int headBPX = (int) Math.floor(headPosX); + int headBPY = (int) Math.floor(headPosY); + int headBPZ = (int) Math.floor(headPosZ); + if (worldObj.getHeightValue(headBPX, headBPZ) < headBPY) { + speed *= 0.675; + } + } + moveHead(speed); } } @@ -180,12 +196,45 @@ public class TileQuarry extends TileAbstractBuilder implements IHasWork, ISidedI } protected void dig() { - int rf = (int) Math.ceil(BuildCraftFactory.MINING_RF_COST_PER_BLOCK * BuildCraftFactory.miningMultiplier); - - if (!consumeEnergy(rf)) { + if (worldObj.isRemote) { return; } + if (miner == null) { + // Hmm. + stage = Stage.IDLE; + return; + } + + int rfTaken = miner.acceptEnergy(getBattery().getEnergyStored()); + getBattery().useEnergy(rfTaken, rfTaken, false); + + if (miner.hasMined()) { + // Collect any lost items laying around + double[] head = getHead(); + AxisAlignedBB axis = AxisAlignedBB.getBoundingBox(head[0] - 2, head[1] - 2, head[2] - 2, head[0] + 3, head[1] + 3, head[2] + 3); + List result = worldObj.getEntitiesWithinAABB(EntityItem.class, axis); + for (int ii = 0; ii < result.size(); ii++) { + if (result.get(ii) instanceof EntityItem) { + EntityItem entity = (EntityItem) result.get(ii); + if (entity.isDead) { + continue; + } + + ItemStack mineable = entity.getEntityItem(); + if (mineable.stackSize <= 0) { + continue; + } + CoreProxy.proxy.removeEntity(entity); + miner.mineStack(mineable); + } + } + + stage = Stage.IDLE; + miner = null; + } + } + protected void idling() { if (!findTarget(true)) { // I believe the issue is box going null becuase of bad chunkloader positioning if (arm != null && box != null) { @@ -194,7 +243,7 @@ public class TileQuarry extends TileAbstractBuilder implements IHasWork, ISidedI stage = Stage.DONE; } else { - stage = Stage.DIGGING; + stage = Stage.MOVING; } movingHorizontally = true; @@ -392,94 +441,11 @@ public class TileQuarry extends TileAbstractBuilder implements IHasWork, ISidedI return; } - int i = targetX; - int j = targetY - 1; - int k = targetZ; - - Block block = worldObj.getBlock(i, j, k); - int meta = worldObj.getBlockMetadata(i, j, k); - - BlockEvent.BreakEvent breakEvent = new BlockEvent.BreakEvent(i, j, k, worldObj, block, meta, - CoreProxy.proxy.getBuildCraftPlayer((WorldServer) worldObj).get()); - MinecraftForge.EVENT_BUS.post(breakEvent); - - if (!breakEvent.isCanceled() && isQuarriableBlock(i, j, k)) { - // Share this with mining well! - - List stacks = BlockUtils.getItemStackFromBlock((WorldServer) worldObj, i, j, k); - - if (stacks != null) { - for (ItemStack s : stacks) { - if (s != null) { - mineStack(s); - } - } - } - - worldObj.playAuxSFXAtEntity( - null, - 2001, - i, - j, - k, - Block.getIdFromBlock(block) - + (meta << 12)); - - if (block.hasTileEntity(meta)) { - worldObj.removeTileEntity(i, j, k); - } - - worldObj.setBlockToAir(i, j, k); - } - - // Collect any lost items laying around - double[] head = getHead(); - AxisAlignedBB axis = AxisAlignedBB.getBoundingBox(head[0] - 2, head[1] - 2, head[2] - 2, head[0] + 3, head[1] + 3, head[2] + 3); - List result = worldObj.getEntitiesWithinAABB(EntityItem.class, axis); - for (int ii = 0; ii < result.size(); ii++) { - if (result.get(ii) instanceof EntityItem) { - EntityItem entity = (EntityItem) result.get(ii); - if (entity.isDead) { - continue; - } - - ItemStack mineable = entity.getEntityItem(); - if (mineable.stackSize <= 0) { - continue; - } - CoreProxy.proxy.removeEntity(entity); - mineStack(mineable); - } - } - - stage = Stage.IDLE; - } - - private void mineStack(ItemStack stack) { - // First, try to add to a nearby chest - stack.stackSize -= Utils.addToRandomInventoryAround(worldObj, xCoord, yCoord, zCoord, stack); - - // Second, try to add to adjacent pipes - if (stack.stackSize > 0) { - stack.stackSize -= Utils.addToRandomPipeAround(worldObj, xCoord, yCoord, zCoord, ForgeDirection.UNKNOWN, stack); - } - - // Lastly, throw the object away - if (stack.stackSize > 0) { - float f = worldObj.rand.nextFloat() * 0.8F + 0.1F; - float f1 = worldObj.rand.nextFloat() * 0.8F + 0.1F; - float f2 = worldObj.rand.nextFloat() * 0.8F + 0.1F; - - EntityItem entityitem = new EntityItem(worldObj, xCoord + f, yCoord + f1 + 0.5F, zCoord + f2, stack); - - entityitem.lifespan = BuildCraftCore.itemLifespan; - entityitem.delayBeforeCanPickup = 10; - - float f3 = 0.05F; - entityitem.motionX = (float) worldObj.rand.nextGaussian() * f3; - entityitem.motionY = (float) worldObj.rand.nextGaussian() * f3 + 1.0F; - entityitem.motionZ = (float) worldObj.rand.nextGaussian() * f3; - worldObj.spawnEntityInWorld(entityitem); + if (isQuarriableBlock(targetX, targetY - 1, targetZ)) { + miner = new BlockMiner(worldObj, this, targetX, targetY - 1, targetZ); + stage = Stage.DIGGING; + } else { + stage = Stage.IDLE; } } @@ -504,7 +470,6 @@ public class TileQuarry extends TileAbstractBuilder implements IHasWork, ISidedI @Override public void destroy() { - if (arm != null) { arm.setDead(); } @@ -512,6 +477,10 @@ public class TileQuarry extends TileAbstractBuilder implements IHasWork, ISidedI arm = null; frameProducer = false; + + if (miner != null) { + miner.invalidate(); + } } @Override