diff options
Diffstat (limited to 'src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java')
-rw-r--r-- | src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java | 1033 |
1 files changed, 1033 insertions, 0 deletions
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java b/src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java new file mode 100644 index 0000000000..2ff2712952 --- /dev/null +++ b/src/main/java/gtPlusPlus/xmod/gregtech/common/helpers/TreeFarmHelper.java @@ -0,0 +1,1033 @@ +package gtPlusPlus.xmod.gregtech.common.helpers; + +import static gtPlusPlus.core.lib.CORE.ConfigSwitches.enableTreeFarmerParticles; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import com.google.common.collect.Lists; + +import gnu.trove.set.hash.THashSet; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.Optional; +import cpw.mods.fml.common.eventhandler.Event.Result; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; + +import gregtech.api.enums.*; +import net.minecraft.block.Block; +import net.minecraft.block.BlockAir; +import net.minecraft.block.IGrowable; +import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.server.S23PacketBlockChange; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.ChunkPosition; +import net.minecraft.world.World; + +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.items.GT_MetaGenerated_Tool; +import gregtech.common.items.GT_MetaGenerated_Item_02; + +import gtPlusPlus.api.objects.Logger; +import gtPlusPlus.api.objects.data.AutoMap; +import gtPlusPlus.api.objects.minecraft.BlockPos; +import gtPlusPlus.core.lib.CORE; +import gtPlusPlus.core.lib.LoadedMods; +import gtPlusPlus.core.players.FakeFarmer; +import gtPlusPlus.core.slots.SlotBuzzSaw.SAWTOOL; +import gtPlusPlus.core.util.Utils; +import gtPlusPlus.core.util.math.MathUtils; +import gtPlusPlus.core.util.minecraft.FluidUtils; +import gtPlusPlus.core.util.minecraft.ItemUtils; +import gtPlusPlus.core.util.minecraft.particles.BlockBreakParticles; +import gtPlusPlus.core.util.reflect.ReflectionUtils; +import gtPlusPlus.xmod.gregtech.common.items.MetaGeneratedGregtechItems; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.BonemealEvent; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.oredict.OreDictionary; + +public class TreeFarmHelper { + + public static final FluidStack fertT1 = FluidUtils.getFluidStack("fluid.fertiliser", 3); + public static final FluidStack fertT2 = FluidUtils.getFluidStack("fluid.un18fertiliser", 2); + public static final FluidStack fertT3 = FluidUtils.getFluidStack("fluid.un32fertiliser", 1); + private static final int sawOreId = OreDictionary.getOreID(ToolDictNames.craftingToolSaw.name()); + + public static ITexture[][][] getTextureSet() { + final ITexture[][][] rTextures = new ITexture[10][17][]; + for (byte i = -1; i < 16; i++) { + rTextures[0][i + 1] = TreeFarmHelper.getFront(i); + rTextures[1][i + 1] = TreeFarmHelper.getBack(i); + rTextures[2][i + 1] = TreeFarmHelper.getBottom(i); + rTextures[3][i + 1] = TreeFarmHelper.getTop(i); + rTextures[4][i + 1] = TreeFarmHelper.getSides(i); + rTextures[5][i + 1] = TreeFarmHelper.getFrontActive(i); + rTextures[6][i + 1] = TreeFarmHelper.getBackActive(i); + rTextures[7][i + 1] = TreeFarmHelper.getBottomActive(i); + rTextures[8][i + 1] = TreeFarmHelper.getTopActive(i); + rTextures[9][i + 1] = TreeFarmHelper.getSidesActive(i); + } + return rTextures; + } + + public static ITexture[] getFront(final byte aColor) { + return new ITexture[]{Textures.BlockIcons.MACHINE_CASINGS[2][aColor + 1]}; + } + + public static ITexture[] getBack(final byte aColor) { + return new ITexture[]{Textures.BlockIcons.MACHINE_CASINGS[2][aColor + 1]}; + } + + public static ITexture[] getBottom(final byte aColor) { + return new ITexture[]{Textures.BlockIcons.MACHINE_CASINGS[2][aColor + 1]}; + } + + public static ITexture[] getTop(final byte aColor) { + return new ITexture[]{Textures.BlockIcons.MACHINE_CASINGS[2][aColor + 1]}; + } + + public static ITexture[] getSides(final byte aColor) { + return new ITexture[]{Textures.BlockIcons.MACHINE_CASINGS[2][aColor + 1]}; + } + + public static ITexture[] getFrontActive(final byte aColor) { + return getFront(aColor); + } + + public static ITexture[] getBackActive(final byte aColor) { + return getBack(aColor); + } + + public static ITexture[] getBottomActive(final byte aColor) { + return getBottom(aColor); + } + + public static ITexture[] getTopActive(final byte aColor) { + return getTop(aColor); + } + + public static ITexture[] getSidesActive(final byte aColor) { + return getSides(aColor); + } + + public static boolean applyBonemeal(final EntityPlayer player, final World world, final int intX, final int intY, final int intZ, final short multiplier){ + final Block block = world.getBlock(intX, intY, intZ); + + + int roll; + int rollNeeded; + + if (multiplier==1){ + roll = MathUtils.randInt(1, 15); + rollNeeded = 15; + } + else if (multiplier==2){ + roll = MathUtils.randInt(1, 10); + rollNeeded = 10; + } + else { + roll = MathUtils.randInt(1, 5); + rollNeeded = 5; + } + + if (roll != rollNeeded){ + return false; + } + + //EntityPlayer player = FakePlayerFactory.getMinecraft((WorldServer)world); + if (!world.isRemote){ + if (enableTreeFarmerParticles){ + world.playAuxSFX(2005, intX, intY, intZ, 0); + } + } + final BonemealEvent event = new BonemealEvent(player, world, block, intX, intY, intZ); + if (MinecraftForge.EVENT_BUS.post(event)){ + Logger.MACHINE_INFO("Not sure why this returned false"); + return false; + } + if (event.getResult() == Result.ALLOW){ + if (!world.isRemote){ + world.playAuxSFX(2005, intX, intY, intZ, 0); + } + return true; + } + if (block instanceof IGrowable){ + final IGrowable igrowable = (IGrowable)block; + if (igrowable.func_149851_a(world, intX, intY, intZ, world.isRemote)){ + if (!world.isRemote){ + if (igrowable.func_149852_a(world, CORE.RANDOM, intX, intY, intZ)){ + igrowable.func_149853_b(world, CORE.RANDOM, intX, intY, intZ); + } + } + return true; + } + } + return false; + } + + public static boolean cleanUp(final IGregTechTileEntity aBaseMetaTileEntity){ + Logger.MACHINE_INFO("called cleanUp()"); + int cleanedUp = 0; + final int xDir = net.minecraftforge.common.util.ForgeDirection.getOrientation(aBaseMetaTileEntity.getBackFacing()).offsetX * 11; + final int zDir = net.minecraftforge.common.util.ForgeDirection.getOrientation(aBaseMetaTileEntity.getBackFacing()).offsetZ * 11; + + for (int h=1;h<175;h++){ + for (int i = -11; i <= 11; i++) { + for (int j = -11; j <= 11; j++) { + + final Block testBlock = aBaseMetaTileEntity.getBlockOffset(xDir + i, h, zDir + j); + + + if + (( + ((i == -8) || (i == 8)) || + ((i == -9) || (i == 9)) || + ((i == -10) || (i == 10)) || + ((i == -11) || (i == 11)) + ) + && + ( + ((j == -8) || (j == 8)) || + ((j == -9) || (j == 9)) || + ((j == -10) || (j == 10)) || + ((j == -11) || (j == 11)) + )){ + + if (!testBlock.getUnlocalizedName().toLowerCase().contains("air") || !testBlock.getUnlocalizedName().toLowerCase().contains("pumpkin")) { + //Logger.WARNING("5:"+testBlock.getUnlocalizedName()); + } else { + aBaseMetaTileEntity.getWorld().setBlock(aBaseMetaTileEntity.getXCoord()+xDir+i, aBaseMetaTileEntity.getYCoord()+h, aBaseMetaTileEntity.getZCoord()+zDir+j, Blocks.bookshelf); + } + } + + + //If not in the middle - don't know how else to check this one without lots of != + if ( + (i != 7) && (i != -7) && (j != 7) && (j != -7) && + (i != 6) && (i != -6) && (j != 6) && (j != -6) && + (i != 5) && (i != -5) && (j != 5) && (j != -5) && + (i != 4) && (i != -4) && (j != 4) && (j != -4) && + (i != 3) && (i != -3) && (j != 3) && (j != -3) && + (i != 2) && (i != -2) && (j != 2) && (j != -2) && + (i != 1) && (i != -1) && (j != 1) && (j != -1) && + (i != 0) && (j != 0) + ){ + + if (!testBlock.getUnlocalizedName().toLowerCase().contains("air") || !testBlock.getUnlocalizedName().toLowerCase().contains("pumpkin")) { + //Logger.WARNING("0:"+testBlock.getUnlocalizedName()); + } else { + aBaseMetaTileEntity.getWorld().setBlock(aBaseMetaTileEntity.getXCoord()+xDir+i, aBaseMetaTileEntity.getYCoord()+h, aBaseMetaTileEntity.getZCoord()+zDir+j, Blocks.melon_block); + } + + + if (isLeaves(testBlock) || isWoodLog(testBlock)){ + //Logger.WARNING("1:"+testBlock.getUnlocalizedName()); + int posiX, posiY, posiZ; + posiX = aBaseMetaTileEntity.getXCoord()+xDir+i; + posiY = aBaseMetaTileEntity.getYCoord()+h; + posiZ = aBaseMetaTileEntity.getZCoord()+zDir+j; + //Utils.LOG_MACHINE_INFO("Cleaning Up some leftovers."); + cleanedUp++; + aBaseMetaTileEntity.getWorld().setBlockToAir(posiX, posiY, posiZ); + new BlockBreakParticles(aBaseMetaTileEntity.getWorld(), posiX, posiY, posiZ, Blocks.dirt); + } + else { + //Utils.LOG_WARNING("2:"+testBlock.getUnlocalizedName()); + } + } + else { + //Utils.LOG_WARNING("1"); + } + + + } + + } + } + Logger.MACHINE_INFO("cleaning up | "+cleanedUp ); + return true; + } + + public static SAWTOOL isCorrectMachinePart(final ItemStack aStack) { + if (aStack != null){ + //Utils.LOG_WARNING("Found "+aStack.getDisplayName()+" in the GUI slot."); + if ((aStack.getItem() instanceof GT_MetaGenerated_Item_02) || (aStack.getItem() instanceof GT_MetaGenerated_Tool)){ + if (OrePrefixes.craftingTool.contains(aStack)){ + if (aStack.getDisplayName().toLowerCase().contains("saw") || aStack.getDisplayName().toLowerCase().contains("gt.metatool.01")){ + if (aStack.getItemDamage() == 10){ + return SAWTOOL.SAW; + } + else if (aStack.getItemDamage() == 140 || aStack.getDisplayName().toLowerCase().contains("gt.metatool.01.140")){ + return SAWTOOL.BUZZSAW; + } + else if (aStack.getItemDamage() == 110 || aStack.getDisplayName().toLowerCase().contains("gt.metatool.01.110")){ + return SAWTOOL.CHAINSAW; + } + else if (aStack.getItemDamage() == 112 || aStack.getDisplayName().toLowerCase().contains("gt.metatool.01.112")){ + return SAWTOOL.CHAINSAW; + } + else if (aStack.getItemDamage() == 114 || aStack.getDisplayName().toLowerCase().contains("gt.metatool.01.114")){ + return SAWTOOL.CHAINSAW; + } + else { + return SAWTOOL.NONE; + } + } + } + } + } + return SAWTOOL.NONE; + } + + public static ToolType getPartType(final ItemStack aStack) { + if (aStack != null){ + //Utils.LOG_WARNING("Found "+aStack.getDisplayName()+" in the GUI slot."); + + if (aStack.getItem() == MetaGeneratedGregtechItems.INSTANCE) { + int aDmg = aStack.getItemDamage(); + if (aDmg >= 32120 && aDmg <= 32128) { + return ToolType.Unbreakable; + } + Logger.INFO("bad Tool in Slot 2 | "+aStack.getUnlocalizedName().toLowerCase() + " | "+aDmg); + return null; + } + + if (aStack.getItem() instanceof GT_MetaGenerated_Tool) { + if (Arrays.stream(OreDictionary.getOreIDs(aStack)).anyMatch(i -> i == sawOreId)) + return ToolType.Breakable; + } + } + Logger.INFO("bad Tool in Slot 4"); + return null; + } + + public static boolean isHumusLoaded = false; + public static boolean isForestryLogsLoaded = false; + public static boolean isForestryFenceLoaded = false; + public static boolean isForestrySaplingsLoaded = false; + public static boolean isForestryLeavesLoaded = false; + public static Block blockHumus; + + public static boolean isForestryValid(){ + if (!LoadedMods.Forestry){ + return false; + } + if (ReflectionUtils.doesClassExist("forestry.core.blocks.BlockSoil")){ + isHumusLoaded = true; + } + if (ReflectionUtils.doesClassExist("forestry.arboriculture.blocks.BlockLog")){ + isForestryLogsLoaded = true; + } + if (ReflectionUtils.doesClassExist("forestry.arboriculture.blocks.BlockArbFence")){ + isForestryFenceLoaded = true; + } + if (ReflectionUtils.doesClassExist("forestry.arboriculture.blocks.BlockSapling")){ + isForestrySaplingsLoaded = true; + } + if (ReflectionUtils.doesClassExist("forestry.arboriculture.blocks.BlockForestryLeaves")){ + isForestryLeavesLoaded = true; + } + return true; + } + + @Optional.Method(modid = "Forestry") + public static Block getHumus(){ + if(blockHumus != null){ + return blockHumus; + } + else if (isHumusLoaded){ + final Class<?> humusClass = ReflectionUtils.getClass("forestry.core.blocks.BlockSoil"); + final ItemStack humusStack = ItemUtils.getCorrectStacktype("Forestry:soil", 1); + if (humusClass != null){ + blockHumus = Block.getBlockFromItem(humusStack.getItem()); + return Block.getBlockFromItem(humusStack.getItem()); + } + } + return null; + } + + public static boolean isWoodLog(final Block log){ + final String tTool = log.getHarvestTool(0); + + if ((log == Blocks.log) || (log == Blocks.log2)){ + return true; + } + + //Forestry/General Compat + if (log.getClass().getName().toLowerCase().contains("blocklog")){ + return true; + } + + //IC2 Rubber Tree Compat + if (log.getClass().getName().toLowerCase().contains("rubwood") || log.getClass().getName().toLowerCase().contains("rubleaves")){ + return true; + } + + return (OrePrefixes.log.contains(new ItemStack(log, 1))&& ((tTool != null) && (tTool.equals("axe")))) || (log.getMaterial() != Material.wood) ? false : (OrePrefixes.fence.contains(new ItemStack(log, 1)) ? false : true); + } + + public static boolean isLeaves(final Block log){ + if (log.getUnlocalizedName().toLowerCase().contains("leaf")){ + return true; + } + if (log.getUnlocalizedName().toLowerCase().contains("leaves")){ + return true; + } + if (log.getLocalizedName().toLowerCase().contains("leaf")){ + return true; + } + if (log.getLocalizedName().toLowerCase().contains("leaves")){ + return true; + } + return OrePrefixes.leaves.contains(new ItemStack(log, 1)) || log.getMaterial() == Material.leaves || OrePrefixes.treeLeaves.contains(new ItemStack(log, 1)) || log.getMaterial() == Material.vine || OrePrefixes.mushroom.contains(new ItemStack(log, 1)) || log.getMaterial() == Material.cactus; + } + + public static boolean isSapling(final Block log){ + if (log != null){ + if (OrePrefixes.sapling.contains(new ItemStack(log, 1))){ + //Logger.WARNING(""+log.getLocalizedName()); + } + if (log.getLocalizedName().toLowerCase().contains("sapling")){ + //Logger.WARNING(""+log.getLocalizedName()); + return true; + } + } + return OrePrefixes.sapling.contains(new ItemStack(log, 1)); + } + + public static boolean isDirtBlock(final Block dirt){ + return (dirt == Blocks.dirt ? true : (dirt == Blocks.grass ? true : (getHumus() == null ? false : (dirt == blockHumus ? true : false)))); + } + + public static boolean isFenceBlock(final Block fence){ + return (fence == Blocks.fence ? true : (fence == Blocks.fence_gate ? true : (fence == Blocks.nether_brick_fence ? true : (OrePrefixes.fence.contains(new ItemStack(fence, 1)) ? true : false)))); + } + + public static boolean isAirBlock(final Block air){ + if (air.getLocalizedName().toLowerCase().contains("air")){ + return true; + } + if (air.getClass().getName().toLowerCase().contains("residual") || air.getClass().getName().toLowerCase().contains("heat")){ + return true; + } + return (air == Blocks.air ? true : (air instanceof BlockAir ? true : false)); + } + + /*public static boolean isSaplingBlock(Block sapling){ + return (sapling == Blocks.sapling ? true : (sapling == Blocks.)) + }*/ + + public static BlockPos checkForLogsInGrowArea(final IGregTechTileEntity aBaseMetaTileEntity) { + final int xDir = net.minecraftforge.common.util.ForgeDirection.getOrientation(aBaseMetaTileEntity.getBackFacing()).offsetX * 7; + final int zDir = net.minecraftforge.common.util.ForgeDirection.getOrientation(aBaseMetaTileEntity.getBackFacing()).offsetZ * 7; + for (int i = -7; i <= 7; i++) { + for (int j = -7; j <= 7; j++) { + for (int h = 0; h <= 1; h++) { + //Farm Floor inner 14x14 + if (((i != -7) && (i != 7)) && ((j != -7) && (j != 7))) { + if (h == 1) { + if (TreeFarmHelper.isWoodLog(aBaseMetaTileEntity.getBlockOffset(xDir + i, h, zDir + j))) { + Logger.INFO("Found a Log"); + return new BlockPos(aBaseMetaTileEntity.getXCoord()+xDir + i, aBaseMetaTileEntity.getYCoord()+h, aBaseMetaTileEntity.getZCoord()+zDir + j, aBaseMetaTileEntity.getWorld()); + } + } + } + } + } + } + return null; + } + + public static ItemStack[] findTreeFromBase(World world, BlockPos h) { + int HARD_LIMIT = 10000; + int mCount = 0; + Logger.INFO("Finding Rest of Tree."); + BlockPos mFirstSpot = h; + Set<BlockPos> mSearchedSpaces = new HashSet<BlockPos>(); + Set<BlockPos> mTreeSet = getConnectedBlocks(world, mFirstSpot, mSearchedSpaces); + Set<Set<BlockPos>> mTreeSet2 = new HashSet<Set<BlockPos>>(); + Set<BlockPos> mFinalTree = new HashSet<BlockPos>(); + Iterator<BlockPos> it = mTreeSet.iterator(); + + + Logger.INFO("Running first iteration."); + while(it.hasNext()){ + BlockPos G = it.next(); + mSearchedSpaces.add(G); + mTreeSet2.add(getConnectedBlocks(world, G, mSearchedSpaces)); + mCount++; + Logger.INFO("First Search: "+G.getLocationString()); + if (mCount > HARD_LIMIT) { + break; + } + } + + mCount = 0; + Iterator<Set<BlockPos>> it2 = mTreeSet2.iterator(); + Iterator<BlockPos> it3; + Logger.INFO("Running second iteration."); + while(it2.hasNext()){ + Set<BlockPos> G = it2.next(); + it3 = G.iterator(); + while(it3.hasNext()){ + BlockPos G2 = it3.next(); + mSearchedSpaces.add(G2); + mFinalTree.add(G2); + mCount++; + Logger.INFO("Second Search: "+G2.getLocationString()); + if (mCount > HARD_LIMIT) { + break; + } + } + if (mCount > HARD_LIMIT) { + break; + } + } + + + if (mFinalTree.size() > 0) { + Logger.INFO("Queuing "+mFinalTree.size()+" to Harvest Manager."); + TreeCutter harvestManager = new TreeCutter(world); + + Iterator<BlockPos> ith = mFinalTree.iterator(); + while(ith.hasNext()){ + BlockPos G = ith.next(); + harvestManager.queue(G); + mCount++; + Logger.INFO("Queued: "+G.getLocationString()); + if (mCount > HARD_LIMIT) { + break; + } + } + + if (harvestManager.isValid) { + ItemStack[] loot = harvestManager.getDrops(); + if (loot.length > 0) { + //Logger.INFO("Returning Drops from harvestManager Queue."); + return loot; + } + } + } + return new ItemStack[] {}; + } + + + public static Set<BlockPos> getConnectedBlocks(World W, BlockPos P, Set<BlockPos> checkedSpaces) { + int HARD_LIMIT = 1000; + int mCount = 0; + Logger.INFO("Finding blocks connected to "+P.getLocationString()+"."); + Set<BlockPos> mCheckedSpaces = checkedSpaces; + Set<BlockPos> mStartSearch = searchSixFaces(W, P, mCheckedSpaces, false); + Set<BlockPos> mSecondSearch = new HashSet<BlockPos>(); + Set<BlockPos> mThirdSearch = new HashSet<BlockPos>(); + Iterator<BlockPos> it = mStartSearch.iterator(); + while(it.hasNext()){ + Logger.INFO("Running first iteration. [II]"); + BlockPos G = it.next(); + mCheckedSpaces.add(G); + Set<BlockPos> mBranchSearch = searchSixFaces(W, G, mCheckedSpaces, true); + Iterator<BlockPos> it2 = mBranchSearch.iterator(); + while(it2.hasNext()){ + Logger.INFO("Running second iteration. [II]"); + BlockPos G2 = it2.next(); + mCheckedSpaces.add(G2); + mSecondSearch.add(G2); + mCount++; + if (mCount > HARD_LIMIT) { + break; + } + } + if (mCount > HARD_LIMIT) { + break; + } + } + mCount = 0; + Iterator<BlockPos> itx = mSecondSearch.iterator(); + while(itx.hasNext()){ + BlockPos G = itx.next(); + mCheckedSpaces.add(G); + Set<BlockPos> mBranchSearch = searchSixFaces(W, G, mCheckedSpaces, true); + Iterator<BlockPos> it2 = mBranchSearch.iterator(); + while(it2.hasNext()){ + BlockPos G2 = it2.next(); + mCheckedSpaces.add(G2); + mThirdSearch.add(G2); + mCount++; + if (mCount > HARD_LIMIT) { + break; + } + } + if (mCount > HARD_LIMIT) { + break; + } + } + return mThirdSearch; + } + + public static Set<BlockPos> searchSixFaces(World W, BlockPos P, Set<BlockPos> checkedSpaces, boolean checkLeaves) { + Set<BlockPos> mConnected = new HashSet<BlockPos>(); + int x = P.xPos; + int y = P.yPos; + int z = P.zPos; + if (checkLeaves) { + if (isWoodLog(W.getBlock(x-1, y, z)) || isLeaves(W.getBlock(x-1, y, z))) { + BlockPos L = new BlockPos(x-1, y, z, W); + if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + } + } + if (isWoodLog(W.getBlock(x+1, y, z)) || isLeaves(W.getBlock(x+1, y, z))) { + BlockPos L = new BlockPos(x+1, y, z, W); + if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + } + } + if (isWoodLog(W.getBlock(x, y-1, z)) || isLeaves(W.getBlock(x, y-1, z))) { + BlockPos L = new BlockPos(x, y-1, z, W); + if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + } + } + if (isWoodLog(W.getBlock(x, y+1, z)) || isLeaves(W.getBlock(x, y+1, z))) { + BlockPos L = new BlockPos(x, y+1, z, W); + if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + } + } + if (isWoodLog(W.getBlock(x, y, z-1)) || isLeaves(W.getBlock(x, y, z-1))) { + BlockPos L = new BlockPos(x, y, z-1, W); + if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + } + } + if (isWoodLog(W.getBlock(x, y, z+1)) || isLeaves(W.getBlock(x, y, z+1))) { + BlockPos L = new BlockPos(x, y, z+1, W); + if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + } + } + } + else { + if (isWoodLog(W.getBlock(x-1, y, z))) { + BlockPos L = new BlockPos(x-1, y, z, W); + //if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + //} + } + if (isWoodLog(W.getBlock(x+1, y, z))) { + BlockPos L = new BlockPos(x+1, y, z, W); + //if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + //} + } + if (isWoodLog(W.getBlock(x, y-1, z))) { + BlockPos L = new BlockPos(x, y-1, z, W); + //if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + //} + } + if (isWoodLog(W.getBlock(x, y+1, z))) { + BlockPos L = new BlockPos(x, y+1, z, W); + //if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + //} + } + if (isWoodLog(W.getBlock(x, y, z-1))) { + BlockPos L = new BlockPos(x, y, z-1, W); + //if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + //} + } + if (isWoodLog(W.getBlock(x, y, z+1))) { + BlockPos L = new BlockPos(x, y, z+1, W); + //if (!checkedSpaces.contains(L)) { + mConnected.add(L); + Logger.INFO("Found Connected. [III]"); + //} + } + } + return mConnected; + } + + + public enum ToolType { + Unbreakable, + Breakable + } + + + /** + * Tree Cutting + */ + + public static class TreeCutter { + + private final World mWorld; + private Map<String, BlockPos> mQueue = new ConcurrentHashMap<String, BlockPos>(); + private AutoMap<ItemStack[]> mDrops = new AutoMap<ItemStack[]>(); + private boolean isValid = true; + + public TreeCutter(World world) { + this.mWorld = world; + } + + public boolean queue(BlockPos pos) { + if (isValid && pos != null) { + //Logger.INFO("Queued: "+pos.getLocationString()); + String hash = Utils.calculateChecksumMD5(pos); + if (hash != null && !mQueue.containsKey(hash)) { + mQueue.put(hash, pos); + return true; + } + } + return false; + } + + private boolean emptyQueue() { + if (isValid) { + Logger.INFO("Emptying Queue."); + if (this.mQueue.size() > 0) { + int totalRemoved = 0; + for (BlockPos h : mQueue.values()) { + final Block block = mWorld.getBlock(h.xPos, h.yPos, h.zPos); + if (block != null) { + final int dropMeta = mWorld.getBlockMetadata(h.xPos, h.yPos, h.zPos); + final ArrayList<ItemStack> blockDrops = block.getDrops(mWorld, h.xPos, h.yPos, h.zPos, dropMeta, 0); + final ItemStack[] drops = ItemUtils.getBlockDrops(blockDrops); + mDrops.put(drops); + //Remove drop that was added to the bus. + mWorld.setBlockToAir(h.xPos, h.yPos, h.zPos); + //new BlockBreakParticles(mWorld, h.xPos, h.yPos, h.zPos, block); + totalRemoved++; + } + } + if (totalRemoved > 0 && mDrops.size() > 0) { + return true; + } + } + } + return false; + } + + public ItemStack[] getDrops() { + //If Queue is successfully cleared and drops are created, let us continue. + if (isValid && emptyQueue()) { + AutoMap<ItemStack> mCollective = new AutoMap<ItemStack>(); + //Iterate ALL of the arrays, add output to a collective. + for (ItemStack[] i : this.mDrops) { + //Array is not null. + if (i != null) { + //Iterate this array. + for (int d=0;d<i.length;d++) { + //Put Output into collective if valid + if (i[d] != null && i[d].stackSize > 0) { + mCollective.put(i[d]); + } + } + } + } + //Build an ItemStack array. + ItemStack[] drops = new ItemStack[mCollective.size()]; + for (int m=0;m<drops.length;m++) { + drops[m] = mCollective.get(m); + } + //Return drops array if it's valid. + if (drops.length > 0) { + isValid = false; + return drops; + } + } + //Invalid or no drops, return empty array. + isValid = false; + return new ItemStack[] {}; + } + + } + + + /** + * Farm AI + */ + private static EntityPlayerMP farmerAI; + public EntityPlayerMP getFakePlayer(World world) { + return farmerAI = checkFakePlayer(world); + } + + public static EntityPlayerMP checkFakePlayer(World world) { + if (farmerAI == null) { + return new FakeFarmer(MinecraftServer.getServer().worldServerForDimension(world.provider.dimensionId)); + } + return farmerAI; + } + + public static boolean onBlockStartBreak (int x, int y, int z, World world){ + final Block wood = world.getBlock(x, y, z); + if (wood == null){ + return false; + } + if (wood.isWood(world, x, y, z) || wood.getMaterial() == Material.sponge) + if(detectTree(world, x,y,z)) { + TreeChopTask chopper = new TreeChopTask(new ChunkPosition(x, y, z), checkFakePlayer(world), 128); + FMLCommonHandler.instance().bus().register(chopper); + // custom block breaking code, don't call vanilla code + return true; + } + //return onBlockStartBreak(stack, x, y, z, player); + return false; + } + + public static boolean detectTree(World world, int pX, int pY, int pZ) { + ChunkPosition pos = null; + Stack<ChunkPosition> candidates = new Stack<>(); + candidates.add(new ChunkPosition(pX, pY, pZ)); + + while (!candidates.isEmpty()) { + ChunkPosition candidate = candidates.pop(); + int curX = candidate.chunkPosX, curY = candidate.chunkPosY, curZ = candidate.chunkPosZ; + + Block block = world.getBlock(curX, curY, curZ); + if ((pos == null || candidate.chunkPosY > pos.chunkPosY) && block.isWood(world, curX, curY, curZ)) { + pos = new ChunkPosition(curX, candidate.chunkPosY + 1, curZ); + // go up + while (world.getBlock(curX, pos.chunkPosY, curZ).isWood(world, curX, pos.chunkPosY, curZ)) { + pos = new ChunkPosition(curX, pos.chunkPosY + 1, curZ); + } + // check if we still have a way diagonally up + candidates.add(new ChunkPosition(curX + 1, pos.chunkPosY + 1, curZ )); + candidates.add(new ChunkPosition(curX , pos.chunkPosY + 1, curZ + 1)); + candidates.add(new ChunkPosition(curX - 1, pos.chunkPosY + 1, curZ )); + candidates.add(new ChunkPosition(curX , pos.chunkPosY + 1, curZ - 1)); + } + } + + // not even one match, so there were no logs. + if (pos == null) { + return false; + } + + // check if there were enough leaves around the last position + // pos now contains the block above the topmost log + // we want at least 5 leaves in the surrounding 26 blocks + int d = 3; + int leaves = 0; + for (int offX = 0; offX < d; offX++) { + for (int offY = 0; offY < d; offY++) { + for (int offZ = 0; offZ < d; offZ++) { + int xPos = pos.chunkPosX -1 + offX, yPos = pos.chunkPosY - 1 + offY, zPos = pos.chunkPosZ - 1 + offZ; + Block leaf = world.getBlock(xPos, yPos, zPos); + if (leaf != null && leaf.isLeaves(world, xPos, yPos, zPos)) { + if (++leaves >= 5) { + return true; + } + } + } + } + } + + // not enough leaves. sorreh + return false; + } + + public static class TreeChopTask { + + public final World world; + public final EntityPlayer player; + public final int blocksPerTick; + + public Queue<ChunkPosition> blocks = Lists.newLinkedList(); + public Set<ChunkPosition> visited = new THashSet<>(); + + public TreeChopTask(ChunkPosition start, EntityPlayer player, int blocksPerTick) { + this.world = player.getEntityWorld(); + this.player = player; + this.blocksPerTick = blocksPerTick; + + this.blocks.add(start); + } + + private void queueCoordinate(int x, int y, int z) { + ChunkPosition pos = new ChunkPosition(x, y, z); + if (!visited.contains(pos)) { + blocks.add(pos); + } + } + + @SubscribeEvent + public void onWorldTick(TickEvent.WorldTickEvent event) { + if (event.side.isClient()) { + finish(); + return; + } + // only if same dimension + if (event.world.provider.dimensionId != world.provider.dimensionId) { + return; + } + + // setup + int left = blocksPerTick; + //NBTTagCompound tags = stack.getTagCompound().getCompoundTag("InfiTool"); + + // continue running + ChunkPosition pos; + while (left > 0) { + // completely done or can't do our job anymore?! + if (blocks.isEmpty()/* || tags.getBoolean("Broken")*/) { + finish(); + return; + } + + pos = blocks.remove(); + if (!visited.add(pos)) { + continue; + } + int x = pos.chunkPosX, y = pos.chunkPosY, z = pos.chunkPosZ; + + Block block = world.getBlock(x, y, z); + int meta = world.getBlockMetadata(x, y, z); + + // can we harvest the block and is effective? + if (!block.isWood(world, x, y, z) || !isWoodLog(block)) { + continue; + } + + // save its neighbors + queueCoordinate(x + 1, y, z ); + queueCoordinate(x, y, z + 1); + queueCoordinate(x - 1, y, z ); + queueCoordinate(x, y, z - 1); + + // also add the layer above.. stupid acacia trees + for (int offX = 0; offX < 3; offX++) { + for (int offZ = 0; offZ < 3; offZ++) { + queueCoordinate(x - 1 + offX, y + 1, z - 1 + offZ); + } + } + + // break it, wooo! + breakExtraBlock(player.worldObj, x, y, z, 0, player, x, y, z); + left--; + } + } + + private void finish() { + // goodbye cruel world + FMLCommonHandler.instance().bus().unregister(this); + } + } + + + public static void breakExtraBlock(World world, int x, int y, int z, int sidehit, EntityPlayer playerEntity, int refX, int refY, int refZ) { + // prevent calling that stuff for air blocks, could lead to unexpected behaviour since it fires events + if (world.isAirBlock(x, y, z)) + return; + + // what? + if(!(playerEntity instanceof EntityPlayerMP)) + return; + EntityPlayerMP player = (EntityPlayerMP) playerEntity; + + // check if the block can be broken, since extra block breaks shouldn't instantly break stuff like obsidian + // or precious ores you can't harvest while mining stone + Block block = world.getBlock(x, y, z); + int meta = world.getBlockMetadata(x, y, z); + + // only effective materials + if (!isWoodLog(block)) + return; + + Block refBlock = world.getBlock(refX, refY, refZ); + float refStrength = ForgeHooks.blockStrength(refBlock, player, world, refX, refY, refZ); + float strength = ForgeHooks.blockStrength(block, player, world, x,y,z); + + // only harvestable blocks that aren't impossibly slow to harvest + if (!ForgeHooks.canHarvestBlock(block, player, meta) || refStrength/strength > 10f) + return; + + // send the blockbreak event + BlockEvent.BreakEvent event = ForgeHooks.onBlockBreakEvent(world, player.theItemInWorldManager.getGameType(), player, x,y,z); + if(event.isCanceled()) + return; + + if (player.capabilities.isCreativeMode) { + block.onBlockHarvested(world, x, y, z, meta, player); + if (block.removedByPlayer(world, player, x, y, z, false)) + block.onBlockDestroyedByPlayer(world, x, y, z, meta); + + // send update to client + if (!world.isRemote) { + player.playerNetServerHandler.sendPacket(new S23PacketBlockChange(x, y, z, world)); + } + return; + } + + // callback to the tool the player uses. Called on both sides. This damages the tool n stuff. + player.getCurrentEquippedItem().func_150999_a(world, block, x, y, z, player); + + // server sided handling + if (!world.isRemote) { + // serverside we reproduce ItemInWorldManager.tryHarvestBlock + + // ItemInWorldManager.removeBlock + block.onBlockHarvested(world, x,y,z, meta, player); + + if(block.removedByPlayer(world, player, x,y,z, true)) // boolean is if block can be harvested, checked above + { + block.onBlockDestroyedByPlayer( world, x,y,z, meta); + block.harvestBlock(world, player, x,y,z, meta); + block.dropXpOnBlockBreak(world, x,y,z, event.getExpToDrop()); + } + + // always send block update to client + player.playerNetServerHandler.sendPacket(new S23PacketBlockChange(x, y, z, world)); + } + // client sided handling + else { + //PlayerControllerMP pcmp = Minecraft.getMinecraft().playerController; + // clientside we do a "this clock has been clicked on long enough to be broken" call. This should not send any new packets + // the code above, executed on the server, sends a block-updates that give us the correct state of the block we destroy. + + // following code can be found in PlayerControllerMP.onPlayerDestroyBlock + world.playAuxSFX(2001, x, y, z, Block.getIdFromBlock(block) + (meta << 12)); + if(block.removedByPlayer(world, player, x,y,z, true)) + { + block.onBlockDestroyedByPlayer(world, x,y,z, meta); + } + // callback to the tool + ItemStack itemstack = player.getCurrentEquippedItem(); + if (itemstack != null) + { + itemstack.func_150999_a(world, block, x, y, z, player); + + if (itemstack.stackSize == 0) + { + player.destroyCurrentEquippedItem(); + } + } + + // send an update to the server, so we get an update back + //if(PHConstruct.extraBlockUpdates) + //Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C07PacketPlayerDigging(2, x,y,z, Minecraft.getMinecraft().objectMouseOver.sideHit)); + } + } + +} |