package pneumaticCraft.common.ai; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.List; import net.minecraft.block.Block; import net.minecraft.item.ItemStack; import net.minecraft.world.ChunkPosition; import net.minecraft.world.IBlockAccess; import pneumaticCraft.common.progwidgets.ProgWidgetAreaItemBase; import pneumaticCraft.common.util.PneumaticCraftUtils; import pneumaticCraft.lib.Log; import cpw.mods.fml.relauncher.ReflectionHelper; public class DroneAIDig extends DroneAIBlockInteraction{ /** * * @param drone * @param speed * @param widget needs to implement IBlockOrdered. */ public DroneAIDig(IDroneBase drone, ProgWidgetAreaItemBase widget){ super(drone, widget); } @Override protected boolean isValidPosition(ChunkPosition pos){ Block block = worldCache.getBlock(pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ); if(!worldCache.isAirBlock(pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ) && !ignoreBlock(block)) { int meta = worldCache.getBlockMetadata(pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ); List<ItemStack> droppedStacks; if(block.canSilkHarvest(drone.getWorld(), drone.getFakePlayer(), pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ, meta)) { droppedStacks = Arrays.asList(new ItemStack[]{getSilkTouchBlock(block, meta)}); } else { droppedStacks = block.getDrops(drone.getWorld(), pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ, meta, 0); } for(ItemStack droppedStack : droppedStacks) { if(widget.isItemValidForFilters(droppedStack, meta)) { swapBestItemToFirstSlot(block, pos); return true; } } } return false; } @Override protected boolean respectClaims(){ return true; } private void swapBestItemToFirstSlot(Block block, ChunkPosition pos){ int bestSlot = 0; float bestSoftness = Float.MIN_VALUE; ItemStack oldCurrentStack = drone.getInventory().getStackInSlot(0); for(int i = 0; i < drone.getInventory().getSizeInventory(); i++) { drone.getInventory().setInventorySlotContents(0, drone.getInventory().getStackInSlot(i)); float softness = block.getPlayerRelativeBlockHardness(drone.getFakePlayer(), drone.getWorld(), pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ); if(softness > bestSoftness) { bestSlot = i; bestSoftness = softness; } } drone.getInventory().setInventorySlotContents(0, oldCurrentStack); if(bestSlot != 0) { ItemStack bestItem = drone.getInventory().getStackInSlot(bestSlot); drone.getInventory().setInventorySlotContents(bestSlot, drone.getInventory().getStackInSlot(0)); drone.getInventory().setInventorySlotContents(0, bestItem); } } @Override protected boolean doBlockInteraction(ChunkPosition pos, double distToBlock){ if(!((FakePlayerItemInWorldManager)drone.getFakePlayer().theItemInWorldManager).isDigging() || !((FakePlayerItemInWorldManager)drone.getFakePlayer().theItemInWorldManager).isAcknowledged()) { int x = pos.chunkPosX; int y = pos.chunkPosY; int z = pos.chunkPosZ; Block block = worldCache.getBlock(x, y, z); if(!ignoreBlock(block) && isBlockValidForFilter(worldCache, drone, pos, widget)) { if(block.getBlockHardness(drone.getWorld(), x, y, z) < 0) { addToBlacklist(pos); drone.addDebugEntry("gui.progWidget.dig.debug.cantDigBlock", pos); drone.setDugBlock(0, 0, 0); return false; } FakePlayerItemInWorldManager manager = (FakePlayerItemInWorldManager)drone.getFakePlayer().theItemInWorldManager; manager.onBlockClicked(x, y, z, 0); if(!manager.isAccepted) { addToBlacklist(pos); drone.addDebugEntry("gui.progWidget.dig.debug.cantDigBlock", pos); drone.setDugBlock(0, 0, 0); return false; } drone.setDugBlock(x, y, z); return true; } drone.setDugBlock(0, 0, 0); return false; } else { return true; } } public static boolean isBlockValidForFilter(IBlockAccess worldCache, IDroneBase drone, ChunkPosition pos, ProgWidgetAreaItemBase widget){ int x = pos.chunkPosX; int y = pos.chunkPosY; int z = pos.chunkPosZ; Block block = worldCache.getBlock(x, y, z); if(!block.isAir(worldCache, x, y, z)) { int meta = worldCache.getBlockMetadata(x, y, z); List<ItemStack> droppedStacks; if(block.canSilkHarvest(drone.getWorld(), drone.getFakePlayer(), x, y, z, meta)) { droppedStacks = Arrays.asList(new ItemStack[]{getSilkTouchBlock(block, meta)}); } else { droppedStacks = block.getDrops(drone.getWorld(), x, y, z, meta, 0); } for(ItemStack droppedStack : droppedStacks) { if(widget.isItemValidForFilters(droppedStack, meta)) { return true; } } } return false; } private static final HashMap<Integer, ItemStack> silkTouchBlocks = new HashMap<Integer, ItemStack>(); private static ItemStack getSilkTouchBlock(Block block, int meta){ ItemStack stack = silkTouchBlocks.get(Block.getIdFromBlock(block)); if(stack == null) { Method method = ReflectionHelper.findMethod(Block.class, block, new String[]{"func_149644_j", "createStackedBlock"}, int.class); try { stack = (ItemStack)method.invoke(block, meta); } catch(Exception e) { Log.error("Reflection failed when trying to get a silk touch block!"); e.printStackTrace(); } silkTouchBlocks.put(Block.getIdFromBlock(block), stack); } return stack.copy(); } private static boolean ignoreBlock(Block block){ return PneumaticCraftUtils.isBlockLiquid(block); } }