package pneumaticCraft.common.progwidgets; import java.util.ArrayList; import java.util.List; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.ai.EntityAIBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; import pneumaticCraft.PneumaticCraft; import pneumaticCraft.client.gui.GuiProgrammer; import pneumaticCraft.client.gui.programmer.GuiProgWidgetImportExport; import pneumaticCraft.common.ai.IDroneBase; import pneumaticCraft.common.item.ItemPlasticPlants; import pneumaticCraft.common.util.IOHelper; import pneumaticCraft.common.util.PneumaticCraftUtils; import pneumaticCraft.lib.Textures; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class ProgWidgetCrafting extends ProgWidget implements ICraftingWidget, ICountWidget{ private boolean useCount; private int count; @Override public void addErrors(List<String> curInfo, List<IProgWidget> widgets){ super.addErrors(curInfo, widgets); boolean usingVariables = false; for(int y = 0; y < 3; y++) { ProgWidgetItemFilter itemFilter = (ProgWidgetItemFilter)getConnectedParameters()[y]; for(int x = 0; x < 3 && itemFilter != null; x++) { if(!itemFilter.getVariable().equals("")) usingVariables = true; itemFilter = (ProgWidgetItemFilter)itemFilter.getConnectedParameters()[0]; } } if(!usingVariables && getRecipeResult(PneumaticCraft.proxy.getClientWorld()) == null) { curInfo.add("gui.progWidget.crafting.error.noCraftingRecipe"); } } @Override public boolean hasStepInput(){ return true; } @Override public Class<? extends IProgWidget> returnType(){ return null; } @Override public Class<? extends IProgWidget>[] getParameters(){ return new Class[]{ProgWidgetItemFilter.class, ProgWidgetItemFilter.class, ProgWidgetItemFilter.class}; } @Override public String getWidgetString(){ return "crafting"; } @Override public int getCraftingColorIndex(){ return ItemPlasticPlants.ENDER_PLANT_DAMAGE; } @Override public WidgetDifficulty getDifficulty(){ return WidgetDifficulty.EASY; } @Override protected ResourceLocation getTexture(){ return Textures.PROG_WIDGET_CRAFTING; } @Override protected boolean hasBlacklist(){ return false; } @Override public InventoryCrafting getCraftingGrid(){ InventoryCrafting invCrafting = new InventoryCrafting(new Container(){ @Override public boolean canInteractWith(EntityPlayer p_75145_1_){ return false; } }, 3, 3); for(int y = 0; y < 3; y++) { ProgWidgetItemFilter itemFilter = (ProgWidgetItemFilter)getConnectedParameters()[y]; for(int x = 0; x < 3 && itemFilter != null; x++) { invCrafting.setInventorySlotContents(y * 3 + x, itemFilter.getFilter()); itemFilter = (ProgWidgetItemFilter)itemFilter.getConnectedParameters()[0]; } } return invCrafting; } private ItemStack getRecipeResult(World world){ return CraftingManager.getInstance().findMatchingRecipe(getCraftingGrid(), world); } public static IRecipe getRecipe(World world, ICraftingWidget widget){ InventoryCrafting craftingGrid = widget.getCraftingGrid(); for(IRecipe recipe : (List<IRecipe>)CraftingManager.getInstance().getRecipeList()) { if(recipe.matches(craftingGrid, world)) { return recipe; } } return null; } @Override public void renderExtraInfo(){ ItemStack recipe = getRecipeResult(PneumaticCraft.proxy.getClientWorld()); if(recipe != null) { ProgWidgetItemFilter.drawItemStack(recipe, 8, getHeight() / 2 - 8, recipe.stackSize + ""); } } @Override public EntityAIBase getWidgetAI(IDroneBase drone, IProgWidget widget){ return new DroneAICrafting(drone, (ICraftingWidget)widget); } public static class DroneAICrafting extends EntityAIBase{ private final ICraftingWidget widget; private final IDroneBase drone; public DroneAICrafting(IDroneBase drone, ICraftingWidget widget){ this.drone = drone; this.widget = widget; } @Override public boolean shouldExecute(){ IRecipe recipe = ProgWidgetCrafting.getRecipe(drone.getWorld(), widget); if(recipe == null) return false; InventoryCrafting craftingGrid = widget.getCraftingGrid(); for(int crafted = 0; !((ICountWidget)widget).useCount() || crafted < ((ICountWidget)widget).getCount(); crafted++) { List<ItemStack>[] equivalentsList = new List[9]; for(int i = 0; i < equivalentsList.length; i++) { ItemStack originalStack = craftingGrid.getStackInSlot(i); if(originalStack != null) { List<ItemStack> equivalents = new ArrayList<ItemStack>(); for(int j = 0; j < drone.getInventory().getSizeInventory(); j++) { ItemStack droneStack = drone.getInventory().getStackInSlot(j); if(droneStack != null && (droneStack.getItem() == originalStack.getItem() || PneumaticCraftUtils.isSameOreDictStack(droneStack, originalStack))) { equivalents.add(droneStack); } } if(equivalents.isEmpty()) return false; equivalentsList[i] = equivalents; } } int[] curIndexes = new int[9]; boolean first = true; boolean hasCrafted = false; while(first || count(curIndexes, equivalentsList)) { first = false; InventoryCrafting craftMatrix = new InventoryCrafting(new Container(){ @Override public boolean canInteractWith(EntityPlayer p_75145_1_){ return false; } }, 3, 3); for(int i = 0; i < 9; i++) { ItemStack stack = equivalentsList[i] == null ? null : equivalentsList[i].get(curIndexes[i]); craftMatrix.setInventorySlotContents(i, stack); } if(recipe.matches(craftMatrix, drone.getWorld())) { if(craft(recipe.getCraftingResult(craftMatrix), craftMatrix)) { hasCrafted = true; break; } } } if(!hasCrafted) return false; } return false; } private boolean count(int[] curIndexes, List<ItemStack>[] equivalentsList){ for(int i = 0; i < equivalentsList.length; i++) { List<ItemStack> list = equivalentsList[i]; curIndexes[i]++; if(list == null || curIndexes[i] >= list.size()) { curIndexes[i] = 0; } else { return true; } } return false; } public boolean craft(ItemStack craftedStack, InventoryCrafting craftMatrix){ for(int i = 0; i < craftMatrix.getSizeInventory(); i++) { int requiredCount = 0; ItemStack stack = craftMatrix.getStackInSlot(i); if(stack != null) { for(int j = 0; j < craftMatrix.getSizeInventory(); j++) { if(stack == craftMatrix.getStackInSlot(j)) { requiredCount++; } } if(requiredCount > stack.stackSize) return false; } } FMLCommonHandler.instance().firePlayerCraftingEvent(drone.getFakePlayer(), craftedStack, craftMatrix); for(int i = 0; i < craftMatrix.getSizeInventory(); ++i) { ItemStack itemstack1 = craftMatrix.getStackInSlot(i); if(itemstack1 != null) { if(itemstack1.getItem().hasContainerItem(itemstack1)) { ItemStack itemstack2 = itemstack1.getItem().getContainerItem(itemstack1); if(itemstack2 != null && itemstack2.isItemStackDamageable() && itemstack2.getItemDamage() > itemstack2.getMaxDamage()) { MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(drone.getFakePlayer(), itemstack2)); continue; } ItemStack remainder = IOHelper.insert(drone.getInventory(), itemstack2.copy(), 0, false); if(remainder != null) { Vec3 pos = drone.getPosition(); EntityItem item = new EntityItem(drone.getWorld(), pos.xCoord, pos.yCoord, pos.zCoord, remainder); drone.getWorld().spawnEntityInWorld(item); } } itemstack1.stackSize--;//As this stack references to the Drones stacks in its inventory, we can do this. } } for(int i = 0; i < drone.getInventory().getSizeInventory(); i++) { ItemStack stack = drone.getInventory().getStackInSlot(i); if(stack != null && stack.stackSize <= 0) { drone.getInventory().setInventorySlotContents(i, null); } } ItemStack remainder = IOHelper.insert(drone.getInventory(), craftedStack, 0, false); if(remainder != null) { Vec3 pos = drone.getPosition(); EntityItem item = new EntityItem(drone.getWorld(), pos.xCoord, pos.yCoord, pos.zCoord, remainder); drone.getWorld().spawnEntityInWorld(item); } return true; } } @Override public boolean useCount(){ return useCount; } @Override public void setUseCount(boolean useCount){ this.useCount = useCount; } @Override public int getCount(){ return count; } @Override public void setCount(int count){ this.count = count; } @Override public void writeToNBT(NBTTagCompound tag){ super.writeToNBT(tag); tag.setBoolean("useCount", useCount); tag.setInteger("count", count); } @Override public void readFromNBT(NBTTagCompound tag){ super.readFromNBT(tag); useCount = tag.getBoolean("useCount"); count = tag.getInteger("count"); } @Override @SideOnly(Side.CLIENT) public GuiScreen getOptionWindow(GuiProgrammer guiProgrammer){ return new GuiProgWidgetImportExport(this, guiProgrammer){ @Override protected boolean showSides(){ return false; } }; } }