diff options
author | Johnson <johnssoft@ya.ru> | 2022-02-21 17:35:05 +0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-21 13:35:05 +0100 |
commit | c2fcf94d8039af85994c3909e7a6f3fc3174f0ec (patch) | |
tree | 8ee5ed4c9165f483af840344bdd714056ae461b4 | |
parent | ff62de0864670a6d99363934f58e1754fc54bc2d (diff) | |
download | GT5-Unofficial-c2fcf94d8039af85994c3909e7a6f3fc3174f0ec.tar.gz GT5-Unofficial-c2fcf94d8039af85994c3909e7a6f3fc3174f0ec.tar.bz2 GT5-Unofficial-c2fcf94d8039af85994c3909e7a6f3fc3174f0ec.zip |
Mining behaviour rework (#936)
* Mining machines drilling addon.
Every machine that uses mining pipes must contain a field with this object and use any interaction with the pipe and drilling solid blocks through it.
Includes all checks for this.
Allows you to reuse the code and ensure the same behavior of the processes of descending and retracting the pipe and mining blocks.
* Mining machines drilling addon - singleblock Miner implementation.
Total refactoring of Miner tile entity.
* Some mining addon fixes
* Fix https://github.com/GTNewHorizons/GT-New-Horizons-Modpack/issues/9733
* Removed some over engineering thoughts
* Checks in the mineBlock method. And we can not descent the pipe while outputs are blocked
* code review fixes
https://github.com/GTNewHorizons/GT5-Unofficial/pull/936
* code review fixes
https://github.com/GTNewHorizons/GT5-Unofficial/pull/936
Co-authored-by: karpov.evgeniy <karpov-em@dartit.ru>
3 files changed, 476 insertions, 264 deletions
diff --git a/src/main/java/gregtech/common/misc/GT_DrillingLogicDelegate.java b/src/main/java/gregtech/common/misc/GT_DrillingLogicDelegate.java new file mode 100644 index 0000000000..8f06f70140 --- /dev/null +++ b/src/main/java/gregtech/common/misc/GT_DrillingLogicDelegate.java @@ -0,0 +1,234 @@ +package gregtech.common.misc; + +import java.util.List; + +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.util.GT_Log; +import gregtech.api.util.GT_ModHandler; +import gregtech.api.util.GT_Utility; +import gregtech.common.blocks.GT_TileEntity_Ores; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.FakePlayer; +import static gregtech.api.enums.GT_Values.debugBlockMiner; + +/** @author Relvl on 27.01.2022 */ +@SuppressWarnings("ObjectEquality") +public class GT_DrillingLogicDelegate { + public static final ItemStack MINING_PIPE_STACK = GT_ModHandler.getIC2Item("miningPipe", 0); + public static final Block MINING_PIPE_BLOCK = GT_Utility.getBlockFromStack(MINING_PIPE_STACK); + public static final Block MINING_PIPE_TIP_BLOCK = GT_Utility.getBlockFromStack(GT_ModHandler.getIC2Item("miningPipeTip", 0)); + + /** The owner machine pointer */ + private final GT_IDrillingLogicDelegateOwner owner; + + /** Is pipe retracting process done and halts? */ + private boolean isRetractDone; + /** Is machine ran out of mining pipes in its inventory and halts? */ + private boolean isWaitingForPipeItem; + /** Pipe tip depth (relative to machine Y position, NEGATIVE). */ + private int tipDepth; + /** Cached fake player */ + private FakePlayer mFakePlayer; + + public GT_DrillingLogicDelegate(GT_IDrillingLogicDelegateOwner owner) { + this.owner = owner; + } + + /** Descents a pipe tip one plock deeper. */ + public boolean descent(IGregTechTileEntity te) { + if (!te.isAllowedToWork()) { + return false; + } + + int xCoord = te.getXCoord(); + int zCoord = te.getZCoord(); + int yCoord = te.getYCoord(); + int checkY = yCoord + tipDepth - 1; + boolean isHitsTheVoid = checkY < 0; + boolean isHitsBedrock = GT_Utility.getBlockHardnessAt(te.getWorld(), xCoord, checkY, zCoord) < 0; + boolean isFakePlayerAllowed = canFakePlayerInteract(te, xCoord, checkY, zCoord); + + if (isHitsTheVoid || isHitsBedrock || !isFakePlayerAllowed) { + // Disable and start retracting process. + te.disableWorking(); + if (debugBlockMiner) { + if (isHitsTheVoid) { + GT_Log.out.println("MINER: Hit bottom"); + } + if (isHitsBedrock) { + GT_Log.out.println("MINER: Hit block with -1 hardness"); + } + if (!isFakePlayerAllowed) { + GT_Log.out.println("MINER: Unable to set mining pipe tip"); + } + } + return false; + } + + // Replace the tip onto pipe + if (te.getBlockOffset(0, tipDepth, 0) == MINING_PIPE_TIP_BLOCK) { + te.getWorld().setBlock(xCoord, yCoord + tipDepth, zCoord, MINING_PIPE_BLOCK); + } + // Get and decrease pipe from the machine + boolean pipeTaken = owner.pullInputs(MINING_PIPE_STACK.getItem(), 1, false); + if (!pipeTaken) { + // If there was nothing - waiting for the pipes (just for prevent unnecessary checks) + isWaitingForPipeItem = true; + return false; + } + + // If there is something - mine it + Block block = te.getBlockOffset(0, tipDepth - 1, 0); + if (!block.isAir(te.getWorld(), xCoord, yCoord, zCoord)) { + mineBlock(te, block, xCoord, yCoord + tipDepth - 1, zCoord); + } + + // Descent the pipe tip + te.getWorld().setBlock(xCoord, yCoord + tipDepth - 1, zCoord, MINING_PIPE_TIP_BLOCK); + tipDepth--; + return true; + } + + public void onOwnerPostTick(IGregTechTileEntity te, long tick) { + // If the machine was disabled - try to retract pipe + if (!te.isAllowedToWork()) { + onPostTickRetract(te, tick); + return; + } + // If the machine was re-enabled - we should reset the retracting process + isRetractDone = false; + } + + /** If the machine are disabled - tried to retract pipe. */ + private void onPostTickRetract(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + if (isRetractDone) { + return; + } + // If retracting process just touch the miner + if (tipDepth == 0) { + isRetractDone = true; + return; + } + // Once per N ticks (depends on tier) + if ((aTick % (owner.getMachineSpeed() / 5)) != 0) { + return; + } + + // Check we can push pipe back to machine (inputs allowed for this case!) + boolean canPush = owner.pushOutputs(MINING_PIPE_STACK, 1, true, true); + if (!canPush) { + return; + } + + // Inspect target block - it should be a pipe tip, else something went wrong. + Block targetBlock = aBaseMetaTileEntity.getBlockOffset(0, tipDepth, 0); + if (targetBlock != MINING_PIPE_TIP_BLOCK && targetBlock != MINING_PIPE_BLOCK) { + return; + } + + // Retract the pipe/tip + int xCoord = aBaseMetaTileEntity.getXCoord(); + int yCoord = aBaseMetaTileEntity.getYCoord(); + int zCoord = aBaseMetaTileEntity.getZCoord(); + int actualDrillY = yCoord + tipDepth; + // Move the pipe tip position + if (actualDrillY < yCoord - 1) { + owner.getBaseMetaTileEntity().getWorld().setBlock(xCoord, actualDrillY + 1, zCoord, MINING_PIPE_TIP_BLOCK); + } + // Remove the old pipe tip + aBaseMetaTileEntity.getWorld().setBlock(xCoord, actualDrillY, zCoord, Blocks.air, 0, /*send to client without neighbour updates*/2); + + // Return the pipe back to the machine (inputs allowed for this case!) + owner.pushOutputs(MINING_PIPE_STACK, 1, false, true); + + tipDepth++; + } + + /** Minings the block if it is possible. */ + public void mineBlock(IGregTechTileEntity te, Block block, int x, int y, int z) { + if (!GT_Utility.eraseBlockByFakePlayer(getFakePlayer(te), x, y, z, true)) { + return; + } + + List<ItemStack> drops = getBlockDrops(block, x, y, z); + + boolean canFitDrops = true; + for (ItemStack drop : drops) { + canFitDrops &= owner.pushOutputs(drop, drop.stackSize, true, false); + } + if (!canFitDrops) { + return; + } + for (ItemStack drop : drops) { + owner.pushOutputs(drop, drop.stackSize, false, false); + } + + short metaData = 0; + TileEntity tTileEntity = owner.getBaseMetaTileEntity().getTileEntity(x, y, z); + if (tTileEntity instanceof GT_TileEntity_Ores) { + metaData = ((GT_TileEntity_Ores)tTileEntity).mMetaData; + } + + ItemStack cobble = GT_Utility.getCobbleForOre(block, metaData); + te.getWorld().setBlock(x, y, z, Block.getBlockFromItem(cobble.getItem()), cobble.getItemDamage(), /*cause updates(1) + send to client(2)*/ 3); + } + + /** Returns NEGATIVE (eg -5) depth of current drilling Y world level. RELATIVELY TO MINER ENTITY! This means '(miner world Y) + depth = (actual world Y)'. */ + public int getTipDepth() { + return tipDepth; + } + + /** Looking for the lowest continuous pipe. */ + public void findTipDepth() { + IGregTechTileEntity ownerTe = owner.getBaseMetaTileEntity(); + if (!ownerTe.isServerSide()) { + return; + } + while (true) { + Block block = ownerTe.getBlockOffset(0, tipDepth - 1, 0); + if (block != MINING_PIPE_BLOCK && block != MINING_PIPE_TIP_BLOCK) { + return; + } + tipDepth--; + } + } + + /** Creates and provides the Fake Player for owners. todo maybe will provide player owner uuid? im sure some servers not allow to fakers, in griefing reasons. */ + public FakePlayer getFakePlayer(IGregTechTileEntity te) { + if (mFakePlayer == null) { + mFakePlayer = GT_Utility.getFakePlayer(te); + } + if (mFakePlayer != null) { + mFakePlayer.setWorld(te.getWorld()); + mFakePlayer.setPosition(te.getXCoord(), te.getYCoord(), te.getZCoord()); + } + return mFakePlayer; + } + + public boolean canFakePlayerInteract(IGregTechTileEntity te, int xCoord, int yCoord, int zCoord) { + return GT_Utility.setBlockByFakePlayer(getFakePlayer(te), xCoord, yCoord, zCoord, MINING_PIPE_TIP_BLOCK, 0, true); + } + + /** Get target block drops. We need to encapsulate everyting of mining in this class. */ + private List<ItemStack> getBlockDrops(final Block oreBlock, int posX, int posY, int posZ) { + return oreBlock.getDrops(owner.getBaseMetaTileEntity().getWorld(), posX, posY, posZ, owner.getBaseMetaTileEntity().getMetaID(posX, posY, posZ), owner.getMachineTier()); + } + + /** Can the owner continue doing its work? If we await new pipes - it cannot. */ + public boolean canContinueDrilling(long tick) { + if (isWaitingForPipeItem) { + if (tick % 5 != 0) { + return false; + } + boolean hasPipe = owner.pullInputs(MINING_PIPE_STACK.getItem(), 1, true); + if (hasPipe) { + isWaitingForPipeItem = false; + } + return hasPipe; + } + return true; + } +} diff --git a/src/main/java/gregtech/common/misc/GT_IDrillingLogicDelegateOwner.java b/src/main/java/gregtech/common/misc/GT_IDrillingLogicDelegateOwner.java new file mode 100644 index 0000000000..f290e8ac8c --- /dev/null +++ b/src/main/java/gregtech/common/misc/GT_IDrillingLogicDelegateOwner.java @@ -0,0 +1,21 @@ +package gregtech.common.misc; + +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +/** @author Relvl on 27.01.2022 */ +public interface GT_IDrillingLogicDelegateOwner extends IMetaTileEntity { + + /** Returns the machine actual tier. */ + int getMachineTier(); + + /** Returns the machine current processing speed. */ + int getMachineSpeed(); + + /** Pulls (or check can pull) items from an input slots. */ + boolean pullInputs(Item item, int count, boolean simulate); + + /** Pushes (or check can push) item to output slots. */ + boolean pushOutputs(ItemStack stack, int count, boolean simulate, boolean allowInputSlots); +} diff --git a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Miner.java b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Miner.java index a11ab7fa41..cf3ed75291 100644 --- a/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Miner.java +++ b/src/main/java/gregtech/common/tileentities/machines/basic/GT_MetaTileEntity_Miner.java @@ -1,5 +1,7 @@ package gregtech.common.tileentities.machines.basic; +import java.util.ArrayList; + import gregtech.api.enums.Textures; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; @@ -7,13 +9,14 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_Log; -import gregtech.api.util.GT_ModHandler; import gregtech.api.util.GT_Utility; import gregtech.common.blocks.GT_Block_Ores_Abstract; import gregtech.common.blocks.GT_TileEntity_Ores; +import gregtech.common.misc.GT_IDrillingLogicDelegateOwner; +import gregtech.common.misc.GT_DrillingLogicDelegate; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; @@ -21,75 +24,85 @@ import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.StatCollector; import net.minecraft.world.ChunkPosition; import net.minecraftforge.common.util.FakePlayer; - -import java.util.ArrayList; - import static gregtech.api.enums.GT_Values.V; import static gregtech.api.enums.GT_Values.debugBlockMiner; -public class GT_MetaTileEntity_Miner extends GT_MetaTileEntity_BasicMachine { - private static final ItemStack MINING_PIPE = GT_ModHandler.getIC2Item("miningPipe", 0); - private static final Block MINING_PIPE_BLOCK = GT_Utility.getBlockFromStack(MINING_PIPE); - private static final Block MINING_PIPE_TIP_BLOCK = GT_Utility.getBlockFromStack(GT_ModHandler.getIC2Item("miningPipeTip", 0)); - - int drillY = 0; - boolean mRetractDone; - - boolean waitMiningPipe; +@SuppressWarnings("ObjectEquality") +public class GT_MetaTileEntity_Miner extends GT_MetaTileEntity_BasicMachine implements GT_IDrillingLogicDelegateOwner { static final int[] RADIUS = {8, 8, 16, 24, 32}; //Miner radius per tier static final int[] SPEED = {160, 160, 80, 40, 20}; //Miner cycle time per tier static final int[] ENERGY = {8, 8, 32, 128, 512}; //Miner energy consumption per tier - private int radiusConfig; //Miner configured radius + /** Miner configured radius */ + private int radiusConfig; + /** Found ore blocks cache of current drill depth */ private final ArrayList<ChunkPosition> oreBlockPositions = new ArrayList<>(); + /** General pipe accessor */ + private final GT_DrillingLogicDelegate pipe = new GT_DrillingLogicDelegate(this); + private final int mSpeed; + public GT_MetaTileEntity_Miner(int aID, String aName, String aNameRegional, int aTier) { super(aID, aName, aNameRegional, aTier, 1, - new String[]{ - "Digging ore instead of you", - "Use Screwdriver to regulate work area", - "Use Soft Mallet to disable and retract the pipe", - ENERGY[aTier] + " EU/t, " + SPEED[aTier] / 20 + " sec per block, no stuttering", - "Maximum work area " + (RADIUS[aTier] * 2 + 1) + "x" + (RADIUS[aTier] * 2 + 1), - "Fortune bonus of " + aTier}, - 2, 2, "Miner.png", "", - TextureFactory.of( - TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_ACTIVE")), - TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_ACTIVE_GLOW")).glow().build()), - TextureFactory.of( - TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE")), - TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_GLOW")).glow().build()), - TextureFactory.of( - TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_ACTIVE")), - TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_ACTIVE_GLOW")).glow().build()), - TextureFactory.of( - TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT")), - TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_GLOW")).glow().build()), - TextureFactory.of( - TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_ACTIVE")), - TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_ACTIVE_GLOW")).glow().build()), - TextureFactory.of( - TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP")), - TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_GLOW")).glow().build()), - TextureFactory.of( - TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_ACTIVE")), - TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_ACTIVE_GLOW")).glow().build()), - TextureFactory.of( - TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM")), - TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_GLOW")).glow().build()) - ); + new String[]{ + "Digging ore instead of you", + "Use Screwdriver to regulate work area", + "Use Soft Mallet to disable and retract the pipe", + String.format("%d EU/t, %d sec per block, no stuttering", ENERGY[aTier], SPEED[aTier] / 20), + String.format("Maximum work area %dx%d", (RADIUS[aTier] * 2 + 1), (RADIUS[aTier] * 2 + 1)), + String.format("Fortune bonus of %d", aTier) + }, + 2, + 2, + "Miner.png", + "", + TextureFactory.of( + TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_ACTIVE")), + TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_ACTIVE_GLOW")).glow().build() + ), + TextureFactory.of( + TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE")), + TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_SIDE_GLOW")).glow().build() + ), + TextureFactory.of( + TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_ACTIVE")), + TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_ACTIVE_GLOW")).glow().build() + ), + TextureFactory.of( + TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT")), + TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_FRONT_GLOW")).glow().build() + ), + TextureFactory.of( + TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_ACTIVE")), + TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_ACTIVE_GLOW")).glow().build() + ), + TextureFactory.of( + TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP")), + TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_TOP_GLOW")).glow().build() + ), + TextureFactory.of( + TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_ACTIVE")), + TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_ACTIVE_GLOW")).glow().build() + ), + TextureFactory.of( + TextureFactory.of(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM")), + TextureFactory.builder().addIcon(new Textures.BlockIcons.CustomIcon("basicmachines/miner/OVERLAY_BOTTOM_GLOW")).glow().build() + ) + ); + mSpeed = SPEED[aTier]; radiusConfig = RADIUS[mTier]; -} + } public GT_MetaTileEntity_Miner(String aName, int aTier, String aDescription, ITexture[][][] aTextures, String aGUIName, String aNEIName) { super(aName, aTier, 1, aDescription, aTextures, 1, 1, aGUIName, aNEIName); + mSpeed = SPEED[aTier]; radiusConfig = RADIUS[mTier]; -} + } public GT_MetaTileEntity_Miner(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures, String aGUIName, String aNEIName) { super(aName, aTier, 1, aDescription, aTextures, 2, 2, aGUIName, aNEIName); + mSpeed = SPEED[aTier]; radiusConfig = RADIUS[mTier]; - } @Override @@ -98,10 +111,18 @@ public class GT_MetaTileEntity_Miner extends GT_MetaTileEntity_BasicMachine { } @Override + public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) { + pipe.findTipDepth(); + fillOreList(aBaseMetaTileEntity); + } + + @Override protected boolean allowPutStackValidated(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, byte aSide, ItemStack aStack) { - return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, aSide, aStack) && aStack.getItem() == MINING_PIPE.getItem(); + return super.allowPutStackValidated(aBaseMetaTileEntity, aIndex, aSide, aStack) // + && aStack.getItem() == GT_DrillingLogicDelegate.MINING_PIPE_STACK.getItem(); } + /** Both output slots must be free to work */ public boolean hasFreeSpace() { for (int i = getOutputSlot(); i < getOutputSlot() + 2; i++) { if (mInventory[i] != null) { @@ -119,24 +140,28 @@ public class GT_MetaTileEntity_Miner extends GT_MetaTileEntity_BasicMachine { if (radiusConfig >= 0) { radiusConfig--; } - if (radiusConfig < 0) + if (radiusConfig < 0) { radiusConfig = RADIUS[mTier]; - } else { + } + } + else { if (radiusConfig <= RADIUS[mTier]) { radiusConfig++; } - if (radiusConfig > RADIUS[mTier]) + if (radiusConfig > RADIUS[mTier]) { radiusConfig = 0; + } } - GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("GT5U.machines.workareaset") + " " + (radiusConfig * 2 + 1) + "x" + (radiusConfig * 2 + 1));//TODO Add translation support - oreBlockPositions.clear(); + + GT_Utility.sendChatToPlayer( + aPlayer, + String.format("%s %dx%d", StatCollector.translateToLocal("GT5U.machines.workareaset"), (radiusConfig * 2 + 1), (radiusConfig * 2 + 1)) + ); + + // Rebuild ore cache after change config fillOreList(getBaseMetaTileEntity()); } } - @Override - public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) { - fillOreList(aBaseMetaTileEntity); - } @Override public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { @@ -145,281 +170,213 @@ public class GT_MetaTileEntity_Miner extends GT_MetaTileEntity_BasicMachine { if (!aBaseMetaTileEntity.isServerSide()) { return; } - // If the machine was disabled - try to retract pipe - if (!aBaseMetaTileEntity.isAllowedToWork()){ + + // Pipe workaround + pipe.onOwnerPostTick(aBaseMetaTileEntity, aTick); + + if (!aBaseMetaTileEntity.isAllowedToWork()) { mMaxProgresstime = 0; - onPostTickRetract(aBaseMetaTileEntity, aTick); + if (debugBlockMiner) { + GT_Log.out.println("MINER: Disabled"); + } return; } - // If the machine was re-enabled - we should reset the retracting process - mRetractDone = false; - - boolean hasFreeSpace = hasFreeSpace(); - boolean hasEnergy = aBaseMetaTileEntity.isUniversalEnergyStored(ENERGY[mTier] * (SPEED[mTier] - mProgresstime)); - if (!hasEnergy || !hasFreeSpace){ + if (!hasFreeSpace()) { mMaxProgresstime = 0; if (debugBlockMiner) { - if (!aBaseMetaTileEntity.isAllowedToWork()) { - GT_Log.out.println("MINER: Disabled"); - } - if (!hasEnergy) { - GT_Log.out.println("MINER: Not enough energy yet, want " + (ENERGY[mTier] * SPEED[mTier]) + " have " + aBaseMetaTileEntity.getUniversalEnergyStored()); - } - if (!hasFreeSpace) { - GT_Log.out.println("MINER: No free space"); - } + GT_Log.out.println("MINER: No free space"); } return; } - ItemStack minigPipeStack = getMiningPipe(0); - if (waitMiningPipe){ - if (minigPipeStack == null || minigPipeStack.stackSize == 0){ - mMaxProgresstime = 0; - if (debugBlockMiner){ - GT_Log.out.println("MINER: Pipe found in input"); - } - return; + if (!aBaseMetaTileEntity.isUniversalEnergyStored((long)ENERGY[mTier] * (mSpeed - mProgresstime))) { + mMaxProgresstime = 0; + if (debugBlockMiner) { + GT_Log.out.println("MINER: Not enough energy yet, want " + (ENERGY[mTier] * mSpeed) + " have " + aBaseMetaTileEntity.getUniversalEnergyStored()); } + return; + } + + /* Checks if machine are waiting new mining pipe item */ + if (!pipe.canContinueDrilling(aTick)) { + mMaxProgresstime = 0; + return; } + mMaxProgresstime = mSpeed; + aBaseMetaTileEntity.decreaseStoredEnergyUnits(ENERGY[mTier], true); - mMaxProgresstime = SPEED[mTier]; - - if (mProgresstime == SPEED[mTier] - 1) { - if (drillY == 0 || oreBlockPositions.isEmpty()) { - moveOneDown(aBaseMetaTileEntity); - } else { - ChunkPosition oreBlockPos; - int x = 0, y = 0, z = 0; + + // Real working only when progress done. TODO some legacy code... refactorings needed + if (mProgresstime == mSpeed - 1) { + if (pipe.getTipDepth() == 0 || oreBlockPositions.isEmpty()) { + boolean descends = pipe.descent(aBaseMetaTileEntity); + if (descends) { + fillOreList(aBaseMetaTileEntity); + } + } + else { + int x; + int y; + int z; Block oreBlock; - int oreBlockMetadata = 0; + boolean isOre; do { - oreBlockPos = oreBlockPositions.remove(0); + ChunkPosition oreBlockPos = oreBlockPositions.remove(0); oreBlock = aBaseMetaTileEntity.getBlockOffset(oreBlockPos.chunkPosX, oreBlockPos.chunkPosY, oreBlockPos.chunkPosZ); x = aBaseMetaTileEntity.getXCoord() + oreBlockPos.chunkPosX; y = aBaseMetaTileEntity.getYCoord() + oreBlockPos.chunkPosY; z = aBaseMetaTileEntity.getZCoord() + oreBlockPos.chunkPosZ; - oreBlockMetadata = getBaseMetaTileEntity().getWorld().getBlockMetadata(x, y, z); + isOre = GT_Utility.isOre(oreBlock, aBaseMetaTileEntity.getWorld().getBlockMetadata(x, y, z)); } // someone else might have removed the block - while (!GT_Utility.isOre(oreBlock, oreBlockMetadata) && !oreBlockPositions.isEmpty()); + while (!isOre && !oreBlockPositions.isEmpty()); - if (GT_Utility.isOre(oreBlock, oreBlockMetadata)) { - mineBlock(aBaseMetaTileEntity, oreBlock, x, y, z); + if (isOre) { + pipe.mineBlock(aBaseMetaTileEntity, oreBlock, x, y, z); } } } } - /** - * If the machine are disabled - tried to retract pipe - */ - private void onPostTickRetract(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { - if (mRetractDone) { - return; - } - // If retracting process just touch the miner - if (drillY == 0) { - mRetractDone = true; - return; - } - // Once per N ticks (depends on tier) - if ((aTick % (SPEED[mTier] / 5)) != 0) { - return; - } - // Check the pipe fits the first output slot - int outSlotIndex = getOutputSlot(); - ItemStack outSlotItem = this.mInventory[outSlotIndex]; - if (outSlotItem != null && !GT_Utility.areStacksEqual(outSlotItem, MINING_PIPE)) { - return; - } - // Inspect target block - it should be a pipe tip, else something went wrong. - Block inspectedBlock = aBaseMetaTileEntity.getBlockOffset(0, drillY, 0); - boolean isPipeTip = inspectedBlock == MINING_PIPE_TIP_BLOCK; - if (!isPipeTip) { + /** Finds the ores in current drill Y level */ + private void fillOreList(IGregTechTileEntity aBaseMetaTileEntity) { + if (pipe.getTipDepth() == 0) { return; } - // Retract the pipe/tip - int xCoord = aBaseMetaTileEntity.getXCoord(); - int yCoord = aBaseMetaTileEntity.getYCoord(); - int zCoord = aBaseMetaTileEntity.getZCoord(); - int actualDrillY = yCoord + drillY; - // Move the pipe tip position - if (actualDrillY < yCoord - 1) { - getBaseMetaTileEntity().getWorld().setBlock(xCoord, actualDrillY + 1, zCoord, MINING_PIPE_TIP_BLOCK); - } - // Remove the old pipe tip - aBaseMetaTileEntity.getWorld().setBlockToAir(xCoord, actualDrillY, zCoord); - // Return the pipe into the machine - if (outSlotItem == null) { - final ItemStack copy = MINING_PIPE.copy(); - copy.stackSize = 1; - this.setInventorySlotContents(outSlotIndex, copy); - } else { - this.mInventory[outSlotIndex].stackSize++; + oreBlockPositions.clear(); + for (int z = -radiusConfig; z <= radiusConfig; ++z) { + for (int x = -radiusConfig; x <= radiusConfig; ++x) { + Block block = aBaseMetaTileEntity.getBlockOffset(x, pipe.getTipDepth(), z); + int blockMeta = aBaseMetaTileEntity.getMetaIDOffset(x, pipe.getTipDepth(), z); + + // todo some weird checks. refactorings needed + if (block instanceof GT_Block_Ores_Abstract) { + TileEntity oreEntity = aBaseMetaTileEntity.getTileEntityOffset(x, pipe.getTipDepth(), z); + if (oreEntity instanceof GT_TileEntity_Ores && ((GT_TileEntity_Ores)oreEntity).mNatural) { + oreBlockPositions.add(new ChunkPosition(x, pipe.getTipDepth(), z)); + } + } + else if (GT_Utility.isOre(block, blockMeta)) { + oreBlockPositions.add(new ChunkPosition(x, pipe.getTipDepth(), z)); + } + } } - drillY++; } - /** - * Returns first available pipe from input slots - */ - private ItemStack getMiningPipe(int modify) { + /** Pulls (or check can pull) items from an input slots. */ + @Override + public boolean pullInputs(Item item, int count, boolean simulate) { for (int i = 0; i < mInputSlotCount; i++) { ItemStack stack = getInputAt(i); - if (stack != null && stack.getItem() == MINING_PIPE.getItem() && stack.stackSize > 0) { - stack.stackSize += modify; + if (stack != null && stack.getItem() == item && stack.stackSize >= count) { + if (simulate) { + return true; + } + stack.stackSize -= count; if (stack.stackSize == 0) { mInventory[getInputSlot() + i] = null; } - return stack; + return true; } } - return null; + return false; } - /** - * Findsw the ores in current drill Y level - */ - private void fillOreList(IGregTechTileEntity aBaseMetaTileEntity) { - if (drillY == 0) - return; - for (int z = -radiusConfig; z <= radiusConfig; ++z) { - for (int x = -radiusConfig; x <= radiusConfig; ++x) { - Block block = aBaseMetaTileEntity.getBlockOffset(x, drillY, z); - int blockMeta = aBaseMetaTileEntity.getMetaIDOffset(x, drillY, z); - if (block instanceof GT_Block_Ores_Abstract) { - TileEntity tTileEntity = getBaseMetaTileEntity().getTileEntityOffset(x, drillY, z); - if (tTileEntity instanceof GT_TileEntity_Ores && ((GT_TileEntity_Ores) tTileEntity).mNatural) - oreBlockPositions.add(new ChunkPosition(x, drillY, z)); - } else if (GT_Utility.isOre(block, blockMeta)) - oreBlockPositions.add(new ChunkPosition(x, drillY, z)); - } - } - } + /** Pushes (or check can push) item to output slots. */ @Override - public long maxEUStore() { - return mTier == 1 ? 4096 : V[mTier] * 64; - } - - public boolean moveOneDown(IGregTechTileEntity aBaseMetaTileEntity) { - int xCoord = aBaseMetaTileEntity.getXCoord(); - int zCoord = aBaseMetaTileEntity.getZCoord(); - int yCoord = aBaseMetaTileEntity.getYCoord(); - boolean isHitsTheVoid = yCoord + drillY - 1 < 0; - boolean isHitsBedrock = GT_Utility.getBlockHardnessAt(aBaseMetaTileEntity.getWorld(), xCoord, yCoord + drillY - 1, zCoord) < 0; - boolean isFakePlayerAllowed = GT_Utility.setBlockByFakePlayer(getFakePlayer(aBaseMetaTileEntity), xCoord, yCoord + drillY - 1, zCoord, MINING_PIPE_TIP_BLOCK, 0, true); - - if (isHitsTheVoid || isHitsBedrock || !isFakePlayerAllowed) { - aBaseMetaTileEntity.disableWorking(); - if (debugBlockMiner) { - if (isHitsTheVoid) { - GT_Log.out.println("MINER: Hit bottom"); - } - if (isHitsBedrock) { - GT_Log.out.println("MINER: Hit block with -1 hardness"); - } - if (!isFakePlayerAllowed) { - GT_Log.out.println("MINER: Unable to set mining pipe tip"); + public boolean pushOutputs(ItemStack stack, int count, boolean simulate, boolean allowInputSlots) { + int startSlot = allowInputSlots ? getInputSlot() : getOutputSlot(); + int maxSlot = mInventory.length; + for (int i = startSlot; i < maxSlot; i++) { + ItemStack slot = mInventory[i]; + if (slot == null || slot.stackSize == 0) { + if (!simulate) { + ItemStack copy = stack.copy(); + copy.stackSize = count; + mInventory[i] = copy; } + return true; } - return false; - } - // Replace the tip onto pipe - if (aBaseMetaTileEntity.getBlockOffset(0, drillY, 0) == MINING_PIPE_TIP_BLOCK) { - aBaseMetaTileEntity.getWorld().setBlock(xCoord, yCoord + drillY, zCoord, MINING_PIPE_BLOCK); - } - // Get and decrease pipe from the machine - ItemStack pipeInSlot = getMiningPipe(-1); - if (pipeInSlot == null) { - // If there was nothing - wainting for the pipes (just for prevent unnecessary checks) - waitMiningPipe = true; - return false; - } - // If there is something - mine it (todo don't matter what? maybe some checks like in mining method?) - Block block = aBaseMetaTileEntity.getBlockOffset(0, drillY - 1, 0); - if (block != Blocks.air) { - mineBlock(aBaseMetaTileEntity, block, xCoord, yCoord + drillY - 1, zCoord); - } - // Raise the pipe tip - aBaseMetaTileEntity.getWorld().setBlock(xCoord, yCoord + drillY - 1, zCoord, MINING_PIPE_TIP_BLOCK); - drillY--; - fillOreList(aBaseMetaTileEntity); - return true; - } - - public void mineBlock(IGregTechTileEntity aBaseMetaTileEntity, Block block, int x, int y, int z) { - if (!GT_Utility.eraseBlockByFakePlayer(getFakePlayer(aBaseMetaTileEntity), x, y, z, true)) { - if (debugBlockMiner) - GT_Log.out.println("MINER: FakePlayer cannot mine block at " + x + ", " + y + ", " + z); - } else { - ArrayList<ItemStack> drops = getBlockDrops(block, x, y, z); - if (drops.size() > 0) - mOutputItems[0] = drops.get(0); - if (drops.size() > 1) - mOutputItems[1] = drops.get(1); - - short metaData = 0; - TileEntity tTileEntity = getBaseMetaTileEntity().getTileEntity(x, y, z); - if (tTileEntity instanceof GT_TileEntity_Ores) { - metaData = ((GT_TileEntity_Ores) tTileEntity).mMetaData; + else if (GT_Utility.areStacksEqual(slot, stack) && slot.stackSize <= slot.getMaxStackSize() - count) { + if (!simulate) { + slot.stackSize += count; + } + return true; } - - ItemStack cobble = GT_Utility.getCobbleForOre(block, metaData); - aBaseMetaTileEntity.getWorld().setBlock(x, y, z, Block.getBlockFromItem(cobble.getItem()), cobble.getItemDamage(), 3); - if (debugBlockMiner) - GT_Log.out.println("MINER: Mining GT ore block at " + x + " " + y + " " + z); } + return false; } - private ArrayList<ItemStack> getBlockDrops(final Block oreBlock, int posX, int posY, int posZ) { - final int blockMeta = getBaseMetaTileEntity().getMetaID(posX, posY, posZ); - return oreBlock.getDrops(getBaseMetaTileEntity().getWorld(), posX, posY, posZ, blockMeta, mTier); + @Override + public long maxEUStore() { + return Math.max(V[mTier] * 64, 4096); } @Override public void setItemNBT(NBTTagCompound aNBT) { super.setItemNBT(aNBT); - aNBT.setByte("mTier", mTier); aNBT.setInteger("radiusConfig", radiusConfig); } @Override public void saveNBTData(NBTTagCompound aNBT) { super.saveNBTData(aNBT); - aNBT.setInteger("drillY", drillY); aNBT.setInteger("radiusConfig", radiusConfig); } @Override public void loadNBTData(NBTTagCompound aNBT) { super.loadNBTData(aNBT); - // todo actually we need to find pipes from the 0Y in the up direction until the miner, and don't need to save it - drillY = aNBT.getInteger("drillY"); - if (aNBT.hasKey("radiusConfig")) - radiusConfig = aNBT.getInteger("radiusConfig"); - } - - private FakePlayer mFakePlayer = null; - - protected FakePlayer getFakePlayer(IGregTechTileEntity aBaseTile) { - if (mFakePlayer == null) - mFakePlayer = GT_Utility.getFakePlayer(aBaseTile); - if (mFakePlayer != null) { - mFakePlayer.setWorld(aBaseTile.getWorld()); - mFakePlayer.setPosition(aBaseTile.getXCoord(), aBaseTile.getYCoord(), aBaseTile.getZCoord()); + if (aNBT.hasKey("radiusConfig")) { + int newRadius = aNBT.getInteger("radiusConfig"); + if (RADIUS[mTier] <= newRadius && newRadius > 0) { + radiusConfig = newRadius; + } } - return mFakePlayer; } @Override public String[] getInfoData() { return new String[]{ - EnumChatFormatting.BLUE+StatCollector.translateToLocal("GT5U.machines.miner")+EnumChatFormatting.RESET, - StatCollector.translateToLocal("GT5U.machines.workarea")+": " + EnumChatFormatting.GREEN + (radiusConfig * 2 + 1)+ - EnumChatFormatting.RESET+" " + StatCollector.translateToLocal("GT5U.machines.blocks") + String.format("%s%s%s", EnumChatFormatting.BLUE, StatCollector.translateToLocal("GT5U.machines.miner"), EnumChatFormatting.RESET), + String.format("%s: %s%d%s %s", + StatCollector.translateToLocal("GT5U.machines.workarea"), + EnumChatFormatting.GREEN, + (radiusConfig * 2 + 1), + EnumChatFormatting.RESET, + StatCollector.translateToLocal("GT5U.machines.blocks") + ) }; } + @Override + public int getMachineTier() { + return mTier; + } + + @Override + public int getMachineSpeed() { + return mSpeed; + } + + /** @deprecated This method are obsolete, and may be removed in further updates. Please use 'this.getPipe().descent()' access! */ + @Deprecated + public boolean moveOneDown(IGregTechTileEntity tileEntity) { + boolean descends = pipe.descent(tileEntity); + if (descends) { + fillOreList(tileEntity); + } + return descends; + } + + /** @deprecated This method are obsolete, and may be removed in further updates. Please use 'this.getPipe().getFakePlayer(te)' access! */ + @Deprecated + protected FakePlayer getFakePlayer(IGregTechTileEntity aBaseTile) { + return pipe.getFakePlayer(aBaseTile); + } + + public GT_DrillingLogicDelegate getPipe() { + return pipe; + } } |