/** * Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team * http://www.mod-buildcraft.com * * The BuildCraft API is distributed under the terms of the MIT License. * Please check the contents of the license, which should be located * as "LICENSE.API" in the BuildCraft source code distribution. */ package buildcraft.api.blueprints; import java.util.LinkedList; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import buildcraft.api.core.IInvSlot; /** * A schematic is a piece of a blueprint. It allows to stock blocks or entities * to blueprints, and can have a state that moves from a blueprint referential * to a world referential. Although default schematic behavior will be OK for a * lot of objects, specific blocks and entities may be associated with a * dedicated schematic class, which will be instantiated automatically. * * Schematic perform "id translation" in case the block ids between a blueprint * and the world installation are different. Mapping is done through the builder * context. * * Detailed documentation on the schematic behavior can be found on * http://www.mod-buildcraft.com/wiki/doku.php?id=builder_support * * Example of schematics for minecraft blocks are available in the package * buildcraft.core.schematics. */ public abstract class Schematic { /** * Blocks are build in various stages, in order to make sure that a block * can indeed be placed, and that it's unlikely to disturb other blocks. */ public enum BuildingStage { /** * Standalone blocks do not change once placed. */ STANDALONE, /** * Expanding blocks will grow and may disturb other block locations, * like liquids. */ EXPANDING } /** * This is called to verify whether the required item is equal to the * supplied item. * * Primarily rely on this for checking metadata/NBT - the item ID * itself might have been filtered out by previously running code. */ public boolean isItemMatchingRequirement(ItemStack suppliedStack, ItemStack requiredStack) { return BuilderAPI.schematicHelper.isEqualItem(suppliedStack, requiredStack); } /** * This is called each time an item matches a requirement. By default, it * will increase damage of items that can be damaged by the amount of the * requirement, and remove the intended amount of items that can't be * damaged. * * Client may override this behavior. Note that this subprogram may be * called twice with the same parameters, once with a copy of requirements * and stack to check if the entire requirements can be fulfilled, and once * with the real inventory. Implementer is responsible for updating req * (with the remaining requirements if any) and slot (after usage). * * returns what was used (similar to req, but created from slot, so that any * NBT based differences are drawn from the correct source) */ public ItemStack useItem(IBuilderContext context, ItemStack req, IInvSlot slot) { ItemStack stack = slot.getStackInSlot(); ItemStack result = stack.copy(); if (stack.stackSize >= req.stackSize) { result.stackSize = req.stackSize; stack.stackSize -= req.stackSize; req.stackSize = 0; } else { req.stackSize -= stack.stackSize; stack.stackSize = 0; } if (stack.stackSize == 0) { stack.stackSize = 1; if (stack.getItem().hasContainerItem(stack)) { ItemStack newStack = stack.getItem().getContainerItem(stack); slot.setStackInSlot(newStack); } else { slot.setStackInSlot(null); } } return result; } /** * Perform a 90 degree rotation to the slot. */ public void rotateLeft(IBuilderContext context) { } /** * Applies translations to all positions in the schematic to center in the * blueprint referential */ public void translateToBlueprint(Translation transform) { } /** * Apply translations to all positions in the schematic to center in the * builder referential */ public void translateToWorld(Translation transform) { } /** * Translates blocks and item ids to the blueprint referential */ public void idsToBlueprint(MappingRegistry registry) { } /** * Translates blocks and item ids to the world referential */ public void idsToWorld(MappingRegistry registry) { } /** * Initializes a schematic for blueprint according to an objet placed on {x, * y, z} on the world. For blocks, block and meta fields will be initialized * automatically. */ public void initializeFromObjectAt(IBuilderContext context, int x, int y, int z) { } /** * Places the block in the world, at the location specified in the slot, * using the stack in parameters */ public void placeInWorld(IBuilderContext context, int x, int y, int z, LinkedList<ItemStack> stacks) { } /** * Write specific requirements coming from the world to the blueprint. */ public void storeRequirements(IBuilderContext context, int x, int y, int z) { } /** * Returns the requirements needed to build this block. When the * requirements are met, they will be removed all at once from the builder, * before calling writeToWorld. */ public void getRequirementsForPlacement(IBuilderContext context, LinkedList<ItemStack> requirements) { } /** * Returns the amount of energy required to build this slot, depends on the * stacks selected for the build. */ public int getEnergyRequirement(LinkedList<ItemStack> stacksUsed) { int result = 0; if (stacksUsed != null) { for (ItemStack s : stacksUsed) { result += s.stackSize * BuilderAPI.BUILD_ENERGY; } } return result; } /** * Returns the flying stacks to display in the builder animation. */ public LinkedList<ItemStack> getStacksToDisplay( LinkedList<ItemStack> stackConsumed) { return stackConsumed; } /** * Return the stage where this schematic has to be built. */ public BuildingStage getBuildStage () { return BuildingStage.STANDALONE; } /** * Return true if the block on the world correspond to the block stored in * the blueprint at the location given by the slot. By default, this * subprogram is permissive and doesn't take into account metadata. * * Post processing will be called on these blocks. */ public boolean isAlreadyBuilt(IBuilderContext context, int x, int y, int z) { return true; } /** * Return true if the block should not be placed to the world. Requirements * will not be asked on such a block, and building will not be called. * * Post processing will be called on these blocks. */ public boolean doNotBuild() { return false; } /** * Return true if the schematic should not be used at all. This is computed * straight after readFromNBT can be used to deactivate schematics in which * an inconsistency is detected. It will be considered as a block of air * instead. * * Post processing will *not* be called on these blocks. */ public boolean doNotUse() { return false; } /** * Return the maximium building permission for blueprint containing this * schematic. */ public BuildingPermission getBuildingPermission() { return BuildingPermission.ALL; } /** * Called on a block when the blueprint has finished to place all the * blocks. This may be useful to adjust variable depending on surrounding * blocks that may not be there already at initial building. */ public void postProcessing(IBuilderContext context, int x, int y, int z) { } /** * Saves this schematic to the blueprint NBT. */ public void writeSchematicToNBT(NBTTagCompound nbt, MappingRegistry registry) { } /** * Loads this schematic from the blueprint NBT. */ public void readSchematicFromNBT(NBTTagCompound nbt, MappingRegistry registry) { } /** * Returns the number of cycles to wait after building this schematic. Tiles * and entities typically require more wait, around 5 cycles. */ public int buildTime() { return 1; } }