Skip to content

Commit

Permalink
Merge pull request #8 from GTNewHorizons/backport_lumberaxe
Browse files Browse the repository at this point in the history
Backport lumberaxe tree chop task from master
  • Loading branch information
Dream-Master authored Dec 22, 2017
2 parents b99a30c + cbf65f1 commit b7b286c
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 107 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ repositories {
apply plugin: 'forge'
group = 'tconstruct'

sourceCompatibility = 1.7
targetCompatibility = 1.7

// Define properties file
ext.configFile = file "build.properties"

Expand Down
2 changes: 1 addition & 1 deletion build.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ mantle_version=0.3.2.jenkins187
CCLIB_version=1.1.3.136
NEI_version=1.0.4.106
ccc_version=1.0.6.43
mod_version=1.8.9.5-GTNH
mod_version=1.8.9.6-GTNH
waila_version=1.5.3_1.7.10
fmp_version=1.1.2.334
261 changes: 156 additions & 105 deletions src/main/java/tconstruct/items/tools/LumberAxe.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package tconstruct.items.tools;

import java.util.Queue;
import java.util.Set;
import java.util.Stack;

import com.google.common.collect.Lists;

import cpw.mods.fml.relauncher.*;
import gnu.trove.set.hash.THashSet;
import mantle.world.WorldHelper;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.*;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.ChunkPosition;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.BlockEvent;
import tconstruct.library.*;
import tconstruct.library.tools.*;
import tconstruct.tools.TinkerTools;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;

public class LumberAxe extends AOEHarvestTool
{
Expand Down Expand Up @@ -95,117 +104,159 @@ public boolean onBlockStartBreak (ItemStack stack, int x, int y, int z, EntityPl
return super.onBlockStartBreak(stack, x, y, z, player);

if (wood.isWood(world, x, y, z) || wood.getMaterial() == Material.sponge)
if(detectTree(world, x,y,z, wood)) {
NBTTagCompound tags = stack.getTagCompound().getCompoundTag("InfiTool");
int meta = world.getBlockMetadata(x, y, z);
breakTree(world, x, y, z, x, y, z, stack, tags, wood, meta, player);
if(detectTree(world, x,y,z)) {
TreeChopTask chopper = new TreeChopTask((AOEHarvestTool)this, stack, new ChunkPosition(x, y, z), player, 128);
FMLCommonHandler.instance().bus().register(chopper);
// custom block breaking code, don't call vanilla code
return true;
}

return super.onBlockStartBreak(stack, x, y, z, player);
}

private boolean detectTree(World world, int x, int y, int z, Block wood)
{
int height = y;
boolean foundTop = false;
do
{
height++;
Block block = world.getBlock(x, height, z);
if (block != wood)
{
height--;
foundTop = true;
}
} while (!foundTop);

int numLeaves = 0;
if (height - y < 50)
{
for (int xPos = x - 1; xPos <= x + 1; xPos++)
{
for (int yPos = height - 1; yPos <= height + 1; yPos++)
{
for (int zPos = z - 1; zPos <= z + 1; zPos++)
{
Block leaves = world.getBlock(xPos, yPos, zPos);
if (leaves != null && leaves.isLeaves(world, xPos, yPos, zPos))
numLeaves++;
}
}
}
}

return numLeaves > 3;
}
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 AOEHarvestTool tool;
public final ItemStack stack;
public final int blocksPerTick;

public Queue<ChunkPosition> blocks = Lists.newLinkedList();
public Set<ChunkPosition> visited = new THashSet<>();

public TreeChopTask(AOEHarvestTool tool, ItemStack stack, ChunkPosition start, EntityPlayer player, int blocksPerTick) {
this.world = player.getEntityWorld();
this.player = player;
this.tool = tool;
this.stack = stack;
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) || !tool.isEffective(block, meta)) {
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!
tool.breakExtraBlock(player.worldObj, x, y, z, 0, player, x, y, z);
left--;
}
}

private void finish() {
// goodbye cruel world
FMLCommonHandler.instance().bus().unregister(this);
}
}

private void breakTree (World world, int x, int y, int z, int xStart, int yStart, int zStart, ItemStack stack, NBTTagCompound tags, Block bID, int meta, EntityPlayer player)
{
for (int xPos = x - 1; xPos <= x + 1; xPos++)
{
for (int yPos = y; yPos <= y + 1; yPos++)
{
for (int zPos = z - 1; zPos <= z + 1; zPos++)
{
if (!(tags.getBoolean("Broken")))
{
Block localBlock = world.getBlock(xPos, yPos, zPos);
if (bID == localBlock)
{
int localMeta = world.getBlockMetadata(xPos, yPos, zPos);
int hlvl = localBlock.getHarvestLevel(localMeta);
float localHardness = localBlock == null ? Float.MAX_VALUE : localBlock.getBlockHardness(world, xPos, yPos, zPos);

if (hlvl <= tags.getInteger("HarvestLevel") && !(localHardness < 0))
{
boolean cancelHarvest = false;
for (ActiveToolMod mod : TConstructRegistry.activeModifiers)
{
if (mod.beforeBlockBreak(this, stack, xPos, yPos, zPos, player))
cancelHarvest = true;
}

// send blockbreak event
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(x, y, z, world, localBlock, localMeta, player);
event.setCanceled(cancelHarvest);
MinecraftForge.EVENT_BUS.post(event);
cancelHarvest = event.isCanceled();

int xDist = xPos - xStart;
int yDist = yPos - yStart;
int zDist = zPos - zStart;

if (9*xDist*xDist + yDist*yDist + 9*zDist*zDist < 2500 )
{
if (cancelHarvest)
{
breakTree(world, xPos, yPos, zPos, xStart, yStart, zStart, stack, tags, bID, meta, player);
}
else
{
if (localBlock == bID && localMeta % 4 == meta % 4)
{
if (!player.capabilities.isCreativeMode)
{
localBlock.harvestBlock(world, player, x,y,z, localMeta);
onBlockDestroyed(stack, world, localBlock, xPos, yPos, zPos, player);
}

world.setBlockToAir(xPos, yPos, zPos);
if (!world.isRemote)
breakTree(world, xPos, yPos, zPos, xStart, yStart, zStart, stack, tags, bID, meta, player);
}
}
}
}
}
}
}
}
}
}
@Override
public Item getHeadItem ()
{
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/tconstruct/library/tools/HarvestTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public boolean onItemUse (ItemStack stack, EntityPlayer player, World world, int
return used;
}

protected void breakExtraBlock(World world, int x, int y, int z, int sidehit, EntityPlayer playerEntity, int refX, int refY, int refZ) {
public 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;
Expand Down

0 comments on commit b7b286c

Please sign in to comment.