diff --git a/common/buildcraft/api/builder/BlockHandler.java b/common/buildcraft/api/builder/BlockHandler.java index 273545e4..f958b7cc 100644 --- a/common/buildcraft/api/builder/BlockHandler.java +++ b/common/buildcraft/api/builder/BlockHandler.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import net.minecraft.block.Block; +import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.world.World; import net.minecraftforge.common.ForgeDirection; @@ -29,6 +30,15 @@ public class BlockHandler { return handler; } + public static BlockHandler getHandler(BlockSchematic schematic) { +// BlockHandler handler = handlers.get(s); // TODO: replace with mapping -> id code +// if (handler == null) { +// return DEFAULT_HANDLER; +// } +// return handler; + return null; + } + public static void registerHandler(int blockId, BlockHandler handler) { handlers.put(blockId, handler); } @@ -99,20 +109,45 @@ public class BlockHandler { } /** - * Called when items are consumed for this block, an array containing all - * the items listed as a cost is passed in. Use them as you see fit. + * Called when items are consumed for this block. The builder's inventory is + * passed in. Use them as you see fit. * * If the function returns false, the block is not placed. You should not * modify any ItemStack until you have determined that everything you * require is present. */ - public boolean consumeItems(ItemStack[] stacks) { - for (int i = 0; i < stacks.length; i++) { - stacks[i] = Utils.consumeItem(stacks[i]); + public boolean consumeItems(BlockSchematic schematic, IInventory builderInventory) { + List requiredItems = getCostForSchematic(schematic); + List slotsToConsume = new ArrayList(); + for (ItemStack cost : requiredItems) { + boolean found = false; + for (int slot = 0; slot < builderInventory.getSizeInventory(); slot++) { + if (areItemsEqual(builderInventory.getStackInSlot(slot), cost)) { + slotsToConsume.add(slot); + found = true; + break; + } + } + if (!found) + return false; + } + for (Integer slot : slotsToConsume) { + builderInventory.setInventorySlotContents(slot, Utils.consumeItem(builderInventory.getStackInSlot(slot))); } return true; } + private boolean areItemsEqual(ItemStack stack1, ItemStack stack2) { + if (stack1 == null || stack2 == null) + return false; + if (!stack1.isItemEqual(stack2)) + return false; + if (!ItemStack.areItemStackTagsEqual(stack1, stack2)) + return false; + return true; + + } + /** * Can the block be placed currently or is it waiting on some other block to * be placed first? @@ -129,7 +164,8 @@ public class BlockHandler { * the blueprint. Blueprints are always saved facing North. This function * will have to rotate the block accordingly. */ - public void readBlockFromSchematic(World world, int x, int y, int z, ForgeDirection blueprintOrientation, BlockSchematic schematic) { + public boolean readBlockFromSchematic(World world, int x, int y, int z, ForgeDirection blueprintOrientation, BlockSchematic schematic) { + return false; } /** diff --git a/common/buildcraft/api/builder/Blueprint.java b/common/buildcraft/api/builder/Blueprint.java index 3744f599..fd1bc82a 100644 --- a/common/buildcraft/api/builder/Blueprint.java +++ b/common/buildcraft/api/builder/Blueprint.java @@ -1,16 +1,21 @@ /** - * Copyright (c) SpaceToad, 2011-2012 - * http://www.mod-buildcraft.com + * Copyright (c) SpaceToad, 2011-2012 http://www.mod-buildcraft.com * - * 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 + * 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.api.builder; +import buildcraft.core.inventory.StackHelper; +import buildcraft.factory.TileQuarry; +import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.UUID; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -22,12 +27,13 @@ import net.minecraft.nbt.NBTTagList; */ public class Blueprint { - private final String version = "Blueprint-1.0"; + private final String version = "Blueprint-2.0"; private final UUID uuid; private String name; private String creator; private final BlockSchematic[][][] blocks; - private final int sizeX, sizeY, sizeZ; + public final int sizeX, sizeY, sizeZ; + private List costs; public Blueprint(int sizeX, int sizeY, int sizeZ) { this(sizeX, sizeY, sizeZ, UUID.randomUUID()); @@ -56,6 +62,23 @@ public class Blueprint { blocks[x][y][z] = block; } + /** + * Helper function for creating Blueprints in code. + * + * Not recommended for use with complex blocks. + * + * @see TileQuarry + */ + public void setBlock(int x, int y, int z, int id, int meta) { + Block block = Block.blocksList[id]; + if (block == null) { + return; + } + BlockSchematic schematic = new BlockSchematic(block.getUnlocalizedName()); + schematic.metadata = meta; + setBlock(x, y, z, schematic); + } + public BlockSchematic getBlock(int x, int y, int z) { return blocks[x][y][z]; } @@ -73,8 +96,8 @@ public class Blueprint { * * @return List */ - public List getBuildList() { - List list = new LinkedList(); + public LinkedList getBuildList() { + LinkedList list = new LinkedList(); for (int y = 0; y < sizeY; y++) { for (int x = 0; x < sizeX; x++) { for (int z = 0; z < sizeZ; z++) { @@ -85,6 +108,29 @@ public class Blueprint { return list; } + public List getCost() { + if (costs != null) + return costs; + List stacks = new ArrayList(); + for (BlockSchematic schematic : getBuildList()) { + BlockHandler handler = BlockHandler.getHandler(schematic); + List requirements = handler.getCostForSchematic(schematic); + for (ItemStack newStack : requirements) { + if (newStack.stackSize <= 0) + continue; + for (ItemStack oldStack : stacks) { + if (StackHelper.instance().canStacksMerge(oldStack, newStack)) { + newStack.stackSize -= StackHelper.instance().mergeStacks(oldStack, newStack, true); + } + } + if (newStack.stackSize > 0) + stacks.add(newStack); + } + } + costs = Collections.unmodifiableList(stacks); + return costs; + } + public void writeToNBT(NBTTagCompound nbt) { NBTTagList blockList = new NBTTagList(); for (int y = 0; y < sizeY; y++) { @@ -117,7 +163,7 @@ public class Blueprint { int sizeZ = nbt.getInteger("sizeZ"); Blueprint blueprint = new Blueprint(sizeX, sizeY, sizeZ, new UUID(most, least)); - + blueprint.name = nbt.getString("name"); blueprint.creator = nbt.getString("creator"); diff --git a/common/buildcraft/api/builder/BlueprintBuilder.java b/common/buildcraft/api/builder/BlueprintBuilder.java new file mode 100644 index 00000000..64f4aeb7 --- /dev/null +++ b/common/buildcraft/api/builder/BlueprintBuilder.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) SpaceToad, 2011-2012 + * http://www.mod-buildcraft.com + * + * 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.api.builder; + +import buildcraft.api.builder.BlueprintBuilder.SchematicBuilder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import net.minecraft.inventory.IInventory; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeDirection; +import static net.minecraftforge.common.ForgeDirection.EAST; + +/** + * + * @author CovertJaguar + */ +public class BlueprintBuilder { + + public final Blueprint blueprint; + public final ForgeDirection orientation; + public final World worldObj; + public final int x, y, z; + private final IInventory inv; + private final LinkedList buildList; + private final List builders; + + public BlueprintBuilder(Blueprint blueprint, World world, int x, int y, int z, ForgeDirection orientation, IInventory inv) { + this.blueprint = blueprint; + this.orientation = orientation; + this.worldObj = world; + this.x = x; + this.y = y; + this.z = z; + this.inv = inv; + this.buildList = blueprint.getBuildList(); + builders = new ArrayList(buildList.size()); + for (BlockSchematic schematic : buildList) { + builders.add(new SchematicBuilder(schematic)); + } + } + + public List getBuilders() { + return Collections.unmodifiableList(builders); + } + + public class SchematicBuilder { + + public final BlockSchematic schematic; + public final BlockHandler handler; + private boolean complete; + + private SchematicBuilder(BlockSchematic schematic) { + this.schematic = schematic; + this.handler = BlockHandler.getHandler(schematic); + } + + public int getX() { + switch (orientation) { + case SOUTH: + return x - schematic.x; + case EAST: + return x - schematic.z; + case WEST: + return x + schematic.z; + default: + return x + schematic.x; + } + } + + public int getY() { + return y + schematic.y; + } + + public int getZ() { + switch (orientation) { + case SOUTH: + return z - schematic.z; + case EAST: + return z + schematic.x; + case WEST: + return z - schematic.x; + default: + return z + schematic.z; + } + } + + public boolean blockExists() { + return handler.doesBlockMatchSchematic(worldObj, getX(), getY(), getZ(), orientation, schematic); + } + + public boolean canBuild() { + return handler.canPlaceNow(worldObj, getX(), getY(), getZ(), orientation, schematic); + } + + public boolean build() { +// if (blockExists()) { +// markComplete(); +// return false; +// } + +// if (!BlockUtil.canChangeBlock(worldObj, getX(), getY(), getZ())) +// return false; + + if (!canBuild()) + return false; + + if (inv != null && !handler.consumeItems(schematic, inv)) { + return false; + } + + boolean built = handler.readBlockFromSchematic(worldObj, getX(), getY(), getZ(), orientation, schematic); + + if (built) { + markComplete(); + } + + return built; + } + + public boolean isComplete() { + return complete; + } + + public void markComplete() { + complete = true; + } + } +} diff --git a/common/buildcraft/api/builder/BlueprintDatabase.java b/common/buildcraft/api/builder/BlueprintDatabase.java index 418ccfbc..7ecc5bd9 100644 --- a/common/buildcraft/api/builder/BlueprintDatabase.java +++ b/common/buildcraft/api/builder/BlueprintDatabase.java @@ -70,7 +70,7 @@ public class BlueprintDatabase { try { CompressedStreamTools.write(nbt, blueprintFile); } catch (IOException ex) { - Logger.getLogger("Buildcraft").log(Level.WARNING, "Failed to save Blueprint file: {0} {1}", new Object[]{blueprintFile.getName(), ex.getMessage()}); + Logger.getLogger("Buildcraft").log(Level.SEVERE, String.format("Failed to save Blueprint file: %s %s", blueprintFile.getName(), ex.getMessage())); } } @@ -97,7 +97,7 @@ public class BlueprintDatabase { nbt = CompressedStreamTools.read(blueprintFile); break; } catch (IOException ex) { - Logger.getLogger("Buildcraft").log(Level.WARNING, "Failed to load Blueprint file: {0} {1}", new Object[]{blueprintFile.getName(), ex.getMessage()}); + Logger.getLogger("Buildcraft").log(Level.SEVERE, String.format("Failed to load Blueprint file: %s %s", blueprintFile.getName(), ex.getMessage())); } } @@ -120,7 +120,7 @@ public class BlueprintDatabase { NBTTagCompound nbt = CompressedStreamTools.read(blueprintFile); addBlueprint(Blueprint.readFromNBT(nbt)); } catch (IOException ex) { - Logger.getLogger("Buildcraft").log(Level.WARNING, "Failed to load Blueprint file: {0} {1}", new Object[]{blueprintFile.getName(), ex.getMessage()}); + Logger.getLogger("Buildcraft").log(Level.SEVERE, String.format("Failed to load Blueprint file: %s %s", blueprintFile.getName(), ex.getMessage())); } } } diff --git a/common/buildcraft/core/inventory/StackHelper.java b/common/buildcraft/core/inventory/StackHelper.java index 087ae774..3cb2078a 100644 --- a/common/buildcraft/core/inventory/StackHelper.java +++ b/common/buildcraft/core/inventory/StackHelper.java @@ -120,7 +120,7 @@ public class StackHelper { * @param matchNBT * @return true if matches */ - public static boolean isMatchingItem(final ItemStack a, final ItemStack b, final boolean matchDamage, final boolean matchNBT) { + public boolean isMatchingItem(final ItemStack a, final ItemStack b, final boolean matchDamage, final boolean matchNBT) { if (a == null || b == null) { return false; } @@ -142,11 +142,11 @@ public class StackHelper { return true; } - public static boolean isWildcard(ItemStack stack) { + public boolean isWildcard(ItemStack stack) { return isWildcard(stack.getItemDamage()); } - public static boolean isWildcard(int damage) { + public boolean isWildcard(int damage) { return damage == -1 || damage == OreDictionary.WILDCARD_VALUE; } }