/** * 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.blueprints; import java.util.LinkedList; import net.minecraft.item.ItemStack; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import buildcraft.api.blueprints.BuilderAPI; import buildcraft.api.blueprints.SchematicBlockBase; import buildcraft.api.core.BuildCraftAPI; import buildcraft.api.core.IInvSlot; import buildcraft.core.builders.BuildingSlot; import buildcraft.core.builders.BuildingSlotBlock; import buildcraft.core.builders.BuildingSlotBlock.Mode; import buildcraft.core.builders.BuildingSlotIterator; import buildcraft.core.builders.TileAbstractBuilder; import buildcraft.core.lib.inventory.InventoryIterator; import buildcraft.core.lib.utils.BlockUtils; public class BptBuilderTemplate extends BptBuilderBase { private LinkedList<BuildingSlotBlock> clearList = new LinkedList<BuildingSlotBlock>(); private LinkedList<BuildingSlotBlock> buildList = new LinkedList<BuildingSlotBlock>(); private BuildingSlotIterator iteratorBuild, iteratorClear; public BptBuilderTemplate(BlueprintBase bluePrint, World world, int x, int y, int z) { super(bluePrint, world, x, y, z); } @Override protected void internalInit() { if (blueprint.excavate) { for (int j = blueprint.sizeY - 1; j >= 0; --j) { int yCoord = j + y - blueprint.anchorY; if (yCoord < 0 || yCoord >= context.world.getHeight()) { continue; } for (int i = 0; i < blueprint.sizeX; ++i) { int xCoord = i + x - blueprint.anchorX; for (int k = 0; k < blueprint.sizeZ; ++k) { int zCoord = k + z - blueprint.anchorZ; SchematicBlockBase slot = blueprint.get(i, j, k); if (slot == null && !isLocationUsed(xCoord, yCoord, zCoord)) { BuildingSlotBlock b = new BuildingSlotBlock(); b.schematic = null; b.x = xCoord; b.y = yCoord; b.z = zCoord; b.mode = Mode.ClearIfInvalid; b.buildStage = 0; clearList.add(b); } } } } } for (int j = 0; j < blueprint.sizeY; ++j) { int yCoord = j + y - blueprint.anchorY; if (yCoord < 0 || yCoord >= context.world.getHeight()) { continue; } for (int i = 0; i < blueprint.sizeX; ++i) { int xCoord = i + x - blueprint.anchorX; for (int k = 0; k < blueprint.sizeZ; ++k) { int zCoord = k + z - blueprint.anchorZ; SchematicBlockBase slot = blueprint.get(i, j, k); if (slot != null && !isLocationUsed(xCoord, yCoord, zCoord)) { BuildingSlotBlock b = new BuildingSlotBlock(); b.schematic = slot; b.x = xCoord; b.y = yCoord; b.z = zCoord; b.mode = Mode.Build; b.buildStage = 1; buildList.add(b); } } } } iteratorBuild = new BuildingSlotIterator(buildList); iteratorClear = new BuildingSlotIterator(clearList); } private void checkDone() { if (buildList.size() == 0 && clearList.size() == 0) { done = true; } else { done = false; } } @Override public BuildingSlot reserveNextBlock(World world) { return null; } @Override public BuildingSlot getNextBlock(World world, TileAbstractBuilder inv) { if (buildList.size() != 0 || clearList.size() != 0) { BuildingSlotBlock slot = internalGetNextBlock(world, inv); checkDone(); if (slot != null) { return slot; } } else { checkDone(); } return null; } private BuildingSlotBlock internalGetNextBlock(World world, TileAbstractBuilder builder) { BuildingSlotBlock result = null; IInvSlot firstSlotToConsume = null; for (IInvSlot invSlot : InventoryIterator.getIterable(builder, ForgeDirection.UNKNOWN)) { if (!builder.isBuildingMaterialSlot(invSlot.getIndex())) { continue; } ItemStack stack = invSlot.getStackInSlot(); if (stack != null && stack.stackSize > 0) { firstSlotToConsume = invSlot; break; } } // Step 1: Check the cleared iteratorClear.startIteration(); while (iteratorClear.hasNext()) { BuildingSlotBlock slot = iteratorClear.next(); if (slot.buildStage > clearList.getFirst().buildStage) { iteratorClear.reset(); break; } if (!world.blockExists(slot.x, slot.y, slot.z)) { continue; } if (canDestroy(builder, context, slot)) { if (BlockUtils.isUnbreakableBlock(world, slot.x, slot.y, slot.z) || isBlockBreakCanceled(world, slot.x, slot.y, slot.z) || BuildCraftAPI.isSoftBlock(world, slot.x, slot.y, slot.z)) { iteratorClear.remove(); markLocationUsed(slot.x, slot.y, slot.z); } else { consumeEnergyToDestroy(builder, slot); createDestroyItems(slot); result = slot; iteratorClear.remove(); markLocationUsed(slot.x, slot.y, slot.z); break; } } } if (result != null) { return result; } // Step 2: Check the built, but only if we have anything to place and enough energy if (firstSlotToConsume == null) { return null; } iteratorBuild.startIteration(); while (iteratorBuild.hasNext()) { BuildingSlotBlock slot = iteratorBuild.next(); if (slot.buildStage > buildList.getFirst().buildStage) { iteratorBuild.reset(); break; } if (BlockUtils.isUnbreakableBlock(world, slot.x, slot.y, slot.z) || isBlockPlaceCanceled(world, slot.x, slot.y, slot.z, slot.schematic) || !BuildCraftAPI.isSoftBlock(world, slot.x, slot.y, slot.z)) { iteratorBuild.remove(); markLocationUsed(slot.x, slot.y, slot.z); } else if (builder.consumeEnergy(BuilderAPI.BUILD_ENERGY)) { slot.addStackConsumed(firstSlotToConsume.decreaseStackInSlot(1)); result = slot; iteratorBuild.remove(); markLocationUsed(slot.x, slot.y, slot.z); break; } } return result; } }