quarries run slower in rain; add dynamic break energy for mining wells and quarries; add build energy requirement for placing mining pipes

This commit is contained in:
asiekierka 2014-11-27 17:21:42 +01:00
parent 7045964097
commit 496e6b4ccb
8 changed files with 236 additions and 183 deletions

View file

@ -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;

View file

@ -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

View file

@ -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<ItemStack> result = new LinkedList<ItemStack>();
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));

View file

@ -10,5 +10,4 @@ package buildcraft.core.network;
public interface ISynchronizedTile {
BuildCraftPacket getPacketUpdate();
BuildCraftPacket getPacketDescription();
}

View file

@ -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));
}
}

View file

@ -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<ItemStack> 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;
}
}

View file

@ -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<ItemStack> 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);
}

View file

@ -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<ItemStack> 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