diff options
author | ghostflyby <ghostflyby+git@outlook.com> | 2024-01-13 03:12:01 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-12 20:12:01 +0100 |
commit | 78668b68e3020e06e2ff8dfcc1955987c4087288 (patch) | |
tree | 02cdafd035c23f71dba29ad55ae8ea8552ded69f /src/main | |
parent | de5569489df37261b4cf19ac779f14f8d34fe800 (diff) | |
download | GT5-Unofficial-78668b68e3020e06e2ff8dfcc1955987c4087288.tar.gz GT5-Unofficial-78668b68e3020e06e2ff8dfcc1955987c4087288.tar.bz2 GT5-Unofficial-78668b68e3020e06e2ff8dfcc1955987c4087288.zip |
GT wrench capabilities for AE2 blocks and others (#2395)
* GT wrench capabilities for ae blocks
* Fix grid array out of bounds
* Fix shift right ae block disappear for an instant
Diffstat (limited to 'src/main')
7 files changed, 386 insertions, 191 deletions
diff --git a/src/main/java/gregtech/api/interfaces/IToolStats.java b/src/main/java/gregtech/api/interfaces/IToolStats.java index c92a0ef05c..9d8da63b6c 100644 --- a/src/main/java/gregtech/api/interfaces/IToolStats.java +++ b/src/main/java/gregtech/api/interfaces/IToolStats.java @@ -36,7 +36,8 @@ public interface IToolStats { void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID); /** - * + * @implNote if you are only modifying drops, override + * {@link #convertBlockDrops(List, ItemStack, EntityPlayer, Block, int, int, int, byte, int, boolean, BlockEvent.HarvestDropsEvent)} * @param player The player * @param x Block pos * @param y Block pos @@ -156,7 +157,7 @@ public interface IToolStats { boolean isMiningTool(); /** - * aBlock.getHarvestTool(aMetaData) can return the following Values for example. "axe", "pickaxe", "sword", + * {@link Block#getHarvestTool(int)} can return the following Values for example. "axe", "pickaxe", "sword", * "shovel", "hoe", "grafter", "saw", "wrench", "crowbar", "file", "hammer", "plow", "plunger", "scoop", * "screwdriver", "sense", "scythe", "softhammer", "cutter", "plasmatorch" * @@ -168,7 +169,7 @@ public interface IToolStats { /** * This lets you modify the Drop List, when this type of Tool has been used. * - * @return the Amount of modified Items. + * @return the Amount of modified Items, used to determine the extra durability cost */ int convertBlockDrops(List<ItemStack> aDrops, ItemStack aStack, EntityPlayer aPlayer, Block aBlock, int aX, int aY, int aZ, byte aMetaData, int aFortune, boolean aSilkTouch, BlockEvent.HarvestDropsEvent aEvent); diff --git a/src/main/java/gregtech/api/items/GT_MetaGenerated_Tool.java b/src/main/java/gregtech/api/items/GT_MetaGenerated_Tool.java index bff7a36201..de6ca996d5 100644 --- a/src/main/java/gregtech/api/items/GT_MetaGenerated_Tool.java +++ b/src/main/java/gregtech/api/items/GT_MetaGenerated_Tool.java @@ -36,6 +36,7 @@ import net.minecraftforge.common.IShearable; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.world.BlockEvent; +import appeng.api.implementations.items.IAEWrench; import buildcraft.api.tools.IToolWrench; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Optional; @@ -71,7 +72,7 @@ import mrtjp.projectred.api.IScrewdriver; @Optional.Interface(iface = "crazypants.enderio.api.tool.ITool", modid = "EnderIOAPI|Tools"), @Optional.Interface(iface = "mrtjp.projectred.api.IScrewdriver", modid = "ProjRed|Core"), }) public abstract class GT_MetaGenerated_Tool extends GT_MetaBase_Item - implements IDamagableItem, IToolGrafter, IToolCrowbar, IToolWrench, ITool, IScrewdriver { + implements IDamagableItem, IToolGrafter, IToolCrowbar, IToolWrench, ITool, IScrewdriver, IAEWrench { /** * All instances of this Item Class are listed here. This gets used to register the Renderer to all Items of this @@ -777,8 +778,13 @@ public abstract class GT_MetaGenerated_Tool extends GT_MetaBase_Item @Override public boolean canWrench(EntityPlayer player, int x, int y, int z) { if (player == null) return false; - if (player.getCurrentEquippedItem() == null) return false; - if (!isItemStackUsable(player.getCurrentEquippedItem())) return false; + return canWrench(player.getHeldItem(), player, x, y, z); + } + + @Override + public boolean canWrench(ItemStack wrench, EntityPlayer player, int x, int y, int z) { + if (wrench == null) return false; + if (!isItemStackUsable(wrench)) return false; IToolStats tStats = getToolStats(player.getCurrentEquippedItem()); return tStats != null && tStats.isWrench(); } diff --git a/src/main/java/gregtech/api/util/GT_ToolHarvestHelper.java b/src/main/java/gregtech/api/util/GT_ToolHarvestHelper.java index 7416289c79..4263b77be6 100644 --- a/src/main/java/gregtech/api/util/GT_ToolHarvestHelper.java +++ b/src/main/java/gregtech/api/util/GT_ToolHarvestHelper.java @@ -3,6 +3,13 @@ package gregtech.api.util; import net.minecraft.block.Block; import net.minecraft.block.material.Material; +import ic2.core.block.BlockMultiID; +import ic2.core.block.BlockScaffold; +import ic2.core.block.machine.BlockMiningPipe; +import ic2.core.block.machine.BlockMiningTip; +import ic2.core.block.wiring.BlockCable; +import ic2.core.crop.BlockCrop; + public class GT_ToolHarvestHelper { public static boolean isAppropriateTool(Block aBlock, byte aMetaData, String... tTools) { @@ -43,7 +50,14 @@ public class GT_ToolHarvestHelper { } public static boolean isStringEmpty(String s) { - return s == null || s.length() == 0; + return s == null || s.isEmpty(); + } + + public static boolean isIC2Wrenchable(Block block) { + return (block instanceof BlockMultiID && !(block instanceof BlockCable) && !(block instanceof BlockCrop)) + || block instanceof BlockScaffold + || block instanceof BlockMiningPipe + || block instanceof BlockMiningTip; } public static boolean hasNull(Object... obj) { diff --git a/src/main/java/gregtech/common/GT_Client.java b/src/main/java/gregtech/common/GT_Client.java index f9b83c1a34..ebce87fdb5 100644 --- a/src/main/java/gregtech/common/GT_Client.java +++ b/src/main/java/gregtech/common/GT_Client.java @@ -18,6 +18,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Scanner; +import java.util.function.Function; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; @@ -46,6 +47,8 @@ import com.glodblock.github.nei.recipes.extractor.GregTech5RecipeExtractor; import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider; +import appeng.api.util.IOrientable; +import appeng.tile.misc.TileInterface; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Scale; import codechicken.lib.vec.Transformation; @@ -67,7 +70,9 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.interfaces.tileentity.ITurnable; import gregtech.api.items.GT_MetaGenerated_Item; import gregtech.api.metatileentity.BaseMetaPipeEntity; +import gregtech.api.metatileentity.BaseMetaTileEntity; import gregtech.api.metatileentity.MetaPipeEntity; +import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; import gregtech.api.multitileentity.multiblock.base.MultiBlockPart; import gregtech.api.net.GT_Packet_ClientPreference; import gregtech.api.objects.GT_ItemStack; @@ -350,12 +355,18 @@ public class GT_Client extends GT_Proxy implements Runnable { for (final ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) { if (iCoverable.getCoverIDAtSide(tSide) != 0) tConnections |= tSide.flag; } - } else if (tTile instanceof BaseMetaPipeEntity) tConnections = ((BaseMetaPipeEntity) tTile).mConnections; + } else if (tTile instanceof BaseMetaTileEntity baseMetaTile && baseMetaTile.getAlignment() == null) { + if (!aIsSneaking) tConnections |= baseMetaTile.getFrontFacing().flag; + else if (baseMetaTile.getMetaTileEntity() instanceof GT_MetaTileEntity_BasicMachine basicMachine) { + tConnections |= basicMachine.mMainFacing.flag; + } + } else if (tTile instanceof BaseMetaPipeEntity pipeEntity) tConnections = pipeEntity.mConnections; } else if (tTile instanceof IWrenchable wrenchable) { tConnections |= ForgeDirection.getOrientation(wrenchable.getFacing()).flag; } else if (ROTATABLE_VANILLA_BLOCKS.contains(block)) { tConnections |= ForgeDirection.getOrientation(meta).flag; - } + } else if (tTile instanceof TileInterface tileInterface) tConnections |= tileInterface.getUp() + .getOpposite().flag; if (tConnections != 0) { for (ForgeDirection tSide : ForgeDirection.VALID_DIRECTIONS) { @@ -415,24 +426,36 @@ public class GT_Client extends GT_Proxy implements Runnable { } GL11.glEnd(); // draw turning indicator - if (aIsWrench && tTile instanceof IAlignmentProvider) { - final IAlignment tAlignment = ((IAlignmentProvider) (tTile)).getAlignment(); - if (tAlignment != null) { - final ForgeDirection direction = tAlignment.getDirection(); - if (direction.ordinal() == tSideHit) - drawExtendedRotationMarker(ROTATION_MARKER_TRANSFORM_CENTER, aIsSneaking, tAlignment); + Function<ForgeDirection, Transformation[]> getTransform = (ForgeDirection direction) -> { + try { + if (direction.ordinal() == tSideHit) return new Transformation[] { ROTATION_MARKER_TRANSFORM_CENTER }; else if (direction.getOpposite() .ordinal() == tSideHit) { - for (Transformation t : ROTATION_MARKER_TRANSFORMS_CORNER) { - drawExtendedRotationMarker(t, aIsSneaking, tAlignment); - } + return ROTATION_MARKER_TRANSFORMS_CORNER; } else { - drawExtendedRotationMarker( + return new Transformation[] { ROTATION_MARKER_TRANSFORMS_SIDES_TRANSFORMS[ROTATION_MARKER_TRANSFORMS_SIDES[tSideHit * 6 - + direction.ordinal()]], - aIsSneaking, - tAlignment); + + direction.ordinal()]] }; } + } catch (ArrayIndexOutOfBoundsException e) { + return new Transformation[] {}; + } + + }; + + if (aIsWrench && tTile instanceof IAlignmentProvider) { + final IAlignment tAlignment = ((IAlignmentProvider) (tTile)).getAlignment(); + if (tAlignment != null) { + for (var transform : getTransform.apply(tAlignment.getDirection())) { + drawExtendedRotationMarker(transform, aIsSneaking, tAlignment); + } + } + } + if (aIsWrench && tTile instanceof IOrientable orientable + && !(tTile instanceof TileInterface) + && orientable.canBeRotated()) { + for (var transform : getTransform.apply(aIsSneaking ? orientable.getForward() : orientable.getUp())) { + drawExtendedRotationMarker(transform, aIsSneaking, orientable); } } GL20.glUseProgram(program); // resume shader @@ -451,6 +474,10 @@ public class GT_Client extends GT_Proxy implements Runnable { } } + private static void drawExtendedRotationMarker(Transformation transform, boolean sneaking, IOrientable orientable) { + drawRotationMarker(transform); + } + private static void drawRotationMarker(Transformation transform) { if (!rotationMarkerDisplayListCompiled) { rotationMarkerDisplayList = GLAllocation.generateDisplayLists(1); @@ -796,7 +823,9 @@ public class GT_Client extends GT_Proxy implements Runnable { if (GT_Utility.isStackInList(aEvent.currentItem, GregTech_API.sWrenchList)) { if (aTileEntity instanceof ITurnable || ROTATABLE_VANILLA_BLOCKS.contains(aBlock) - || aTileEntity instanceof IWrenchable) drawGrid(aEvent, false, true, aEvent.player.isSneaking()); + || aTileEntity instanceof IWrenchable + || (aTileEntity instanceof IOrientable orientable && orientable.canBeRotated())) + drawGrid(aEvent, false, true, aEvent.player.isSneaking()); return; } diff --git a/src/main/java/gregtech/common/items/behaviors/Behaviour_Wrench.java b/src/main/java/gregtech/common/items/behaviors/Behaviour_Wrench.java index df6f3bb0d4..edafab779f 100644 --- a/src/main/java/gregtech/common/items/behaviors/Behaviour_Wrench.java +++ b/src/main/java/gregtech/common/items/behaviors/Behaviour_Wrench.java @@ -2,21 +2,24 @@ package gregtech.common.items.behaviors; import java.util.Arrays; import java.util.List; +import java.util.function.BooleanSupplier; import net.minecraft.block.Block; -import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.oredict.OreDictionary; +import appeng.api.parts.IPartHost; +import appeng.api.util.IOrientable; +import appeng.tile.misc.TileInterface; import gregtech.api.enums.SoundResource; import gregtech.api.items.GT_MetaBase_Item; import gregtech.api.items.GT_MetaGenerated_Tool; import gregtech.api.util.GT_LanguageManager; -import gregtech.api.util.GT_ModHandler; import gregtech.api.util.GT_Utility; import ic2.api.tile.IWrenchable; @@ -33,150 +36,238 @@ public class Behaviour_Wrench extends Behaviour_None { @Override public boolean onItemUseFirst(GT_MetaBase_Item aItem, ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, ForgeDirection side, float hitX, float hitY, float hitZ) { - if (aWorld.isRemote || aPlayer.isSneaking()) { - return false; - } final Block aBlock = aWorld.getBlock(aX, aY, aZ); if (aBlock == null) { return false; } - final byte aMeta = (byte) aWorld.getBlockMetadata(aX, aY, aZ); + final int aMeta = aWorld.getBlockMetadata(aX, aY, aZ); final short targetSideOrdinal = (short) GT_Utility.determineWrenchingSide(side, hitX, hitY, hitZ) .ordinal(); final TileEntity aTileEntity = aWorld.getTileEntity(aX, aY, aZ); + + final WrenchHandler handler = new WrenchHandler( + aBlock, + aMeta, + targetSideOrdinal, + aTileEntity, + aPlayer, + aWorld, + aX, + aY, + aZ, + aStack, + (GT_MetaGenerated_Tool) aItem, + mCosts); + try { - if (aTileEntity instanceof IWrenchable wrenchable) { - if (wrenchable.wrenchCanSetFacing(aPlayer, targetSideOrdinal)) { - if ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) { - wrenchable.setFacing(targetSideOrdinal); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); - } - return true; + return handler.handle(); + } catch (Throwable ignored) {} + return false; + } + + /** + * <p> + * A class to simplify wrenching operation, + * stopping "checking creative", "trying to damage tool", + * "doing the logic" and "playing sound" again and again. + * This should have been a record, but it's not available in Java 8. + * </p> + * <p> + * {@link WrenchHandler#handle()} is the entry point of main logic. + * </p> + */ + private static class WrenchHandler { + + boolean handle() { + ForgeDirection direction = ForgeDirection.getOrientation(targetSideOrdinal); + + // AE2 logic + // default to change the up facing + // sneak to change the forward facing + if (tileEntity instanceof IOrientable orientable) { + if (!orientable.canBeRotated()) return false; + ForgeDirection front = orientable.getForward(); + ForgeDirection up = orientable.getUp(); + + // mainly for me-interfaces, whose initial orientation is UNKNOWN + if (front == ForgeDirection.UNKNOWN) { + if (direction == ForgeDirection.UP || direction == ForgeDirection.DOWN) + front = ForgeDirection.NORTH; + else front = ForgeDirection.UP; } - if (wrenchable.wrenchCanRemove(aPlayer)) { - final int tDamage = wrenchable.getWrenchDropRate() < 1.0F ? 10 : 3; - if ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, (long) tDamage * this.mCosts))) { - ItemStack tOutput = wrenchable.getWrenchDrop(aPlayer); - for (final ItemStack tStack : aBlock.getDrops(aWorld, aX, aY, aZ, aMeta, 0)) { - if (tOutput == null) { - aWorld.spawnEntityInWorld( - new EntityItem(aWorld, aX + 0.5D, aY + 0.5D, aZ + 0.5D, tStack)); - } else { - aWorld.spawnEntityInWorld( - new EntityItem(aWorld, aX + 0.5D, aY + 0.5D, aZ + 0.5D, tOutput)); - tOutput = null; - } - } - aWorld.setBlockToAir(aX, aY, aZ); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); + + ForgeDirection back = front.getOpposite(); + ForgeDirection down = up.getOpposite(); + + if (tileEntity instanceof TileInterface) { + if (player.isSneaking()) return false; + if (direction == down) { + return doWrenchOperation(costs, () -> { + orientable.setOrientation(ForgeDirection.UNKNOWN, ForgeDirection.UNKNOWN); + return true; + }); } - return true; + // interface's up-side is opposite to the arrow on texture + // make it intuitive by rotating it to the opposite side. + direction = direction.getOpposite(); + up = up.getOpposite(); + } else if (direction == up || direction == front) { + // rotate around the direction axis + final var tempFront = front; + final var tempUp = up; + if (!player.isSneaking() && direction == up) return doWrenchOperation(costs, () -> { + orientable.setOrientation(tempFront.getRotation(tempUp), tempUp); + return true; + }); + if (player.isSneaking() && direction == front) return doWrenchOperation(costs, () -> { + orientable.setOrientation( + tempFront, + tempUp.getRotation(tempFront) + .getRotation(tempFront)); + return true; + }); + } + + if (player.isSneaking()) { + if (direction == up || direction == down) { + orientable.setOrientation(direction, down.getRotation(front.getRotation(direction))); + } else orientable.setOrientation(direction, up); + } else { + if (direction == front || direction == back) { + orientable.setOrientation(back.getRotation(up.getRotation(direction)), direction); + } else orientable.setOrientation(front, direction); } - return true; + + return damageWrench(costs); } - } catch (Throwable ignored) {} - if ((aBlock == Blocks.log) || (aBlock == Blocks.log2) || (aBlock == Blocks.hay_block)) { - if ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) { - aWorld.setBlockMetadataWithNotify(aX, aY, aZ, (aMeta + 4) % 12, 3); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); + if (world.isRemote) return false; + // IC2 Wrenchable + if (tileEntity instanceof IWrenchable wrenchable) { + if (wrenchable.wrenchCanSetFacing(player, targetSideOrdinal)) { + return doWrenchOperation(costs, () -> { + wrenchable.setFacing(targetSideOrdinal); + return true; + }); + } + return false; } - return true; - } - if ((aBlock == Blocks.powered_repeater) || (aBlock == Blocks.unpowered_repeater)) { - if ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) { - aWorld.setBlockMetadataWithNotify(aX, aY, aZ, aMeta / 4 * 4 + (aMeta % 4 + 1) % 4, 3); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); + + if (block == Blocks.powered_repeater || block == Blocks.unpowered_repeater + || block == Blocks.powered_comparator + || block == Blocks.unpowered_comparator) return setBlockMeta(costs, meta / 4 * 4 + (meta % 4 + 1) % 4); + + // hopper cannot face sky + if (block == Blocks.hopper && targetSideOrdinal != 1) return setBlockMeta(costs, targetSideOrdinal); + + if (isVanillaAllSideRotatable(block)) if (meta < 6) return setBlockMeta(costs, targetSideOrdinal); + + // blocks like chests and furnaces have only four directions + if (isVanillaCantFaceAxisY(block)) { + if (targetSideOrdinal > 1) return setBlockMeta(costs, targetSideOrdinal); + else return false; } - return true; - } - if ((aBlock == Blocks.powered_comparator) || (aBlock == Blocks.unpowered_comparator)) { - if ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) { - aWorld.setBlockMetadataWithNotify(aX, aY, aZ, aMeta / 4 * 4 + (aMeta % 4 + 1) % 4, 3); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); + if (tileEntity instanceof IPartHost) return false; + + final int logWoodId = OreDictionary.getOreID("logWood"); + if (Arrays.stream(OreDictionary.getOreIDs(new ItemStack(block))) + .anyMatch(id -> id == logWoodId)) { + // The meta just work + return setBlockMeta(costs, (meta + 4) % 12); } - return true; + + // vanilla block rotate logic + if ((Arrays.asList(block.getValidRotations(world, x, y, z)) + .contains(direction))) return rotateBlock(costs, direction); + return false; + + // GT blocks' rotations are done by blocks themselves after this returning false } - if ((aBlock == Blocks.crafting_table) || (aBlock == Blocks.bookshelf)) { - if ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) { - aWorld.spawnEntityInWorld( - new EntityItem(aWorld, aX + 0.5D, aY + 0.5D, aZ + 0.5D, new ItemStack(aBlock, 1, aMeta))); - aWorld.setBlockToAir(aX, aY, aZ); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); - } - return true; + + private final Block block; + private final short targetSideOrdinal; + private final TileEntity tileEntity; + private final EntityPlayer player; + private final World world; + private final int x, y, z, meta; + private final ItemStack stack; + + private final GT_MetaGenerated_Tool item; + private final int costs; + + public WrenchHandler(Block block, int meta, short targetSideOrdinal, TileEntity tileEntity, EntityPlayer player, + World world, int x, int y, int z, ItemStack stack, GT_MetaGenerated_Tool item, int costs) { + this.block = block; + this.meta = meta; + this.targetSideOrdinal = targetSideOrdinal; + this.tileEntity = tileEntity; + this.player = player; + this.world = world; + this.x = x; + this.y = y; + this.z = z; + this.stack = stack; + this.item = item; + this.costs = costs; } - if (aMeta == targetSideOrdinal) { - if ((aBlock == Blocks.pumpkin) || (aBlock == Blocks.lit_pumpkin) - || (aBlock == Blocks.piston) - || (aBlock == Blocks.sticky_piston) - || (aBlock == Blocks.dispenser) - || (aBlock == Blocks.dropper) - || (aBlock == Blocks.furnace) - || (aBlock == Blocks.lit_furnace) - || (aBlock == Blocks.chest) - || (aBlock == Blocks.trapped_chest) - || (aBlock == Blocks.ender_chest) - || (aBlock == Blocks.hopper)) { - if ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts))) { - aWorld.spawnEntityInWorld( - new EntityItem(aWorld, aX + 0.5D, aY + 0.5D, aZ + 0.5D, new ItemStack(aBlock, 1, 0))); - aWorld.setBlockToAir(aX, aY, aZ); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); - } - return true; - } - } else { - if ((aBlock == Blocks.piston) || (aBlock == Blocks.sticky_piston) - || (aBlock == Blocks.dispenser) - || (aBlock == Blocks.dropper)) { - if ((aMeta < 6) && ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts)))) { - aWorld.setBlockMetadataWithNotify(aX, aY, aZ, targetSideOrdinal, 3); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); - } - return true; - } - if ((aBlock == Blocks.pumpkin) || (aBlock == Blocks.lit_pumpkin) - || (aBlock == Blocks.furnace) - || (aBlock == Blocks.lit_furnace) - || (aBlock == Blocks.chest) - || (aBlock == Blocks.ender_chest) - || (aBlock == Blocks.trapped_chest)) { - if ((targetSideOrdinal > 1) && ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts)))) { - aWorld.setBlockMetadataWithNotify(aX, aY, aZ, targetSideOrdinal, 3); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); - } - return true; - } - if (aBlock == Blocks.hopper) { - if ((targetSideOrdinal != 1) && ((aPlayer.capabilities.isCreativeMode) - || (((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts)))) { - aWorld.setBlockMetadataWithNotify(aX, aY, aZ, targetSideOrdinal, 3); - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); + + /** + * this will run the operation, damage the tool and play the sound if possible (creative mode or + * {@link GT_MetaGenerated_Tool#canWrench(EntityPlayer, int, int, int)}) + * + * @param damage damage to be applied to the wrench + * @param operation the real operation of the click + * @return true if the operation was successful + * @see #setBlockMeta(int, int) + * @see #rotateBlock(int, ForgeDirection) + * @see #rotateBlock(int, ForgeDirection) + */ + boolean doWrenchOperation(int damage, BooleanSupplier operation) { + if (player.capabilities.isCreativeMode || item.canWrench(player, x, y, z)) { + if (operation.getAsBoolean()) { + item.doDamage(stack, damage); + GT_Utility.sendSoundToPlayers(world, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, x, y, z); + return true; } - return true; } + return false; } - if ((Arrays.asList(aBlock.getValidRotations(aWorld, aX, aY, aZ)) - .contains(ForgeDirection.getOrientation(targetSideOrdinal))) - && ((aPlayer.capabilities.isCreativeMode) || (!GT_ModHandler.isElectricItem(aStack)) - || (GT_ModHandler.canUseElectricItem(aStack, this.mCosts))) - && (aBlock.rotateBlock(aWorld, aX, aY, aZ, ForgeDirection.getOrientation(targetSideOrdinal)))) { - if (!aPlayer.capabilities.isCreativeMode) { - ((GT_MetaGenerated_Tool) aItem).doDamage(aStack, this.mCosts); - } - GT_Utility.sendSoundToPlayers(aWorld, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1.0F, aX, aY, aZ); - return true; + + boolean setBlockMeta(int damage, int newMeta) { + return doWrenchOperation(damage, () -> setBlockMetadataWithNotify(newMeta)); } - return false; + + boolean rotateBlock(int damage, ForgeDirection direction) { + return doWrenchOperation(damage, () -> block.rotateBlock(world, x, y, z, direction)); + } + + boolean damageWrench(int damage) { + return doWrenchOperation(damage, () -> true); + } + + private boolean setBlockMetadataWithNotify(int newMeta) { + return world.setBlockMetadataWithNotify(x, y, z, newMeta, 3); + } + + } + + public static boolean isVanillaRotatable(Block block) { + return isVanillaCantFaceAxisY(block) || isVanillaAllSideRotatable(block) || block == Blocks.hopper; + } + + public static boolean isVanillaCantFaceAxisY(Block block) { + return GT_Utility.arrayContains( + block, + Blocks.pumpkin, + Blocks.lit_pumpkin, + Blocks.furnace, + Blocks.lit_furnace, + Blocks.chest, + Blocks.trapped_chest, + Blocks.ender_chest); + } + + public static boolean isVanillaAllSideRotatable(Block block) { + return GT_Utility.arrayContains(block, Blocks.piston, Blocks.sticky_piston, Blocks.dispenser, Blocks.dropper); } @Override diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Crowbar.java b/src/main/java/gregtech/common/tools/GT_Tool_Crowbar.java index f9f82fd373..742d4b3fa0 100644 --- a/src/main/java/gregtech/common/tools/GT_Tool_Crowbar.java +++ b/src/main/java/gregtech/common/tools/GT_Tool_Crowbar.java @@ -1,7 +1,5 @@ package gregtech.common.tools; -import java.util.Iterator; - import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.EntityLivingBase; @@ -10,10 +8,11 @@ import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; +import com.google.common.base.Strings; + import gregtech.api.enums.SoundResource; import gregtech.api.enums.Textures; import gregtech.api.interfaces.IIconContainer; -import gregtech.api.interfaces.IToolStats; import gregtech.api.items.GT_MetaGenerated_Tool; import gregtech.common.items.GT_MetaGenerated_Tool_01; import gregtech.common.items.behaviors.Behaviour_Crowbar; @@ -96,10 +95,9 @@ public class GT_Tool_Crowbar extends GT_Tool { return true; } String tTool = aBlock.getHarvestTool(aMetaData); - if ((tTool == null) || (tTool.equals(""))) { - for (Iterator<IToolStats> i$ = GT_MetaGenerated_Tool_01.INSTANCE.mToolStats.values() - .iterator(); i$.hasNext(); i$.next()) { - if (((i$ instanceof GT_Tool_Crowbar)) && (!((IToolStats) i$).isMinableBlock(aBlock, aMetaData))) { + if (Strings.isNullOrEmpty(tTool)) { + for (var i : GT_MetaGenerated_Tool_01.INSTANCE.mToolStats.values()) { + if (i instanceof GT_Tool_Crowbar && !i.isMinableBlock(aBlock, aMetaData)) { return false; } } diff --git a/src/main/java/gregtech/common/tools/GT_Tool_Wrench.java b/src/main/java/gregtech/common/tools/GT_Tool_Wrench.java index 5a5a69ad80..91ecd71536 100644 --- a/src/main/java/gregtech/common/tools/GT_Tool_Wrench.java +++ b/src/main/java/gregtech/common/tools/GT_Tool_Wrench.java @@ -11,7 +11,6 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; @@ -23,13 +22,14 @@ import net.minecraft.util.IChatComponent; import net.minecraft.world.World; import net.minecraftforge.event.world.BlockEvent; +import appeng.api.parts.IPartHost; +import appeng.block.AEBaseTileBlock; +import appeng.parts.PartPlacement; import gregtech.api.enums.SoundResource; import gregtech.api.enums.Textures; import gregtech.api.interfaces.IIconContainer; -import gregtech.api.interfaces.IToolStats; import gregtech.api.items.GT_MetaGenerated_Tool; import gregtech.api.util.GT_ToolHarvestHelper; -import gregtech.common.items.behaviors.Behaviour_Switch_Mode; import gregtech.common.items.behaviors.Behaviour_Wrench; import ic2.api.tile.IWrenchable; @@ -123,10 +123,13 @@ public class GT_Tool_Wrench extends GT_Tool { } @Override - public boolean isMinableBlock(Block aBlock, byte aMetaData) { - return GT_ToolHarvestHelper.isAppropriateTool(aBlock, aMetaData, "wrench") - || GT_ToolHarvestHelper.isAppropriateMaterial(aBlock, Material.piston) - || GT_ToolHarvestHelper.isSpecialBlock(aBlock, Blocks.hopper, Blocks.dispenser, Blocks.dropper); + public boolean isMinableBlock(Block block, byte aMetaData) { + return GT_ToolHarvestHelper.isAppropriateTool(block, aMetaData, "wrench") + || GT_ToolHarvestHelper.isAppropriateMaterial(block, Material.piston) + || block instanceof AEBaseTileBlock + || GT_ToolHarvestHelper.isSpecialBlock(block, Blocks.crafting_table, Blocks.bookshelf) + || Behaviour_Wrench.isVanillaRotatable(block) + || GT_ToolHarvestHelper.isIC2Wrenchable(block); } @Override @@ -146,7 +149,6 @@ public class GT_Tool_Wrench extends GT_Tool { @Override public void onStatsAddedToTool(GT_MetaGenerated_Tool aItem, int aID) { - aItem.addItemBehavior(aID, new Behaviour_Switch_Mode()); aItem.addItemBehavior(aID, new Behaviour_Wrench(100)); } @@ -161,43 +163,97 @@ public class GT_Tool_Wrench extends GT_Tool { + EnumChatFormatting.WHITE); } - @Override - public float getMiningSpeed(Block block, byte metadata, float mineSpeed, EntityPlayer player, World world, int x, - int y, int z) { - ItemStack holding = player.getCurrentEquippedItem(); - if (holding == null || !(holding.getItem() instanceof GT_MetaGenerated_Tool tool)) return mineSpeed; - - IToolStats stats = tool.getToolStats(holding); - if (stats == null) return mineSpeed; - - TileEntity tile = world.getTileEntity(x, y, z); - if (tile == null) return mineSpeed; - - float newSpeed = Math.max(Float.MIN_NORMAL, getSpeedMultiplier() * getPrimaryMaterial(holding).mToolSpeed); - - if (tile instanceof IWrenchable) return newSpeed; - - return mineSpeed; - } + /** + * <p> + * holding drop from {@link IWrenchable#getWrenchDrop(EntityPlayer)} + * </p> + * Since no tile available during + * {@link #convertBlockDrops(List, ItemStack, EntityPlayer, Block, int, int, int, byte, int, boolean, BlockEvent.HarvestDropsEvent)}, + * this is filled during + * {@link #onBreakBlock(EntityPlayer, int, int, int, Block, byte, TileEntity, BlockEvent.BreakEvent)} + */ + private ItemStack wrenchableDrop = null; + /** + * <p> + * drop rate from {@link IWrenchable#getWrenchDropRate()} + * </p> + * see {@link #wrenchableDrop} + */ + private float wrenchableDropRate = 0.0f; + + /** + * <p> + * prevent recursion from + * {@link AEBaseTileBlock#onBlockActivated(World, int, int, int, EntityPlayer, int, float, float, float)} + * </p> + */ + private boolean LastEventFromThis = false; @Override public void onBreakBlock(@Nonnull EntityPlayer player, int x, int y, int z, @Nonnull Block block, byte metadata, TileEntity tile, @Nonnull BlockEvent.BreakEvent event) { - final World world = player.worldObj; if (tile instanceof IWrenchable wrenchable) { - ItemStack drop = wrenchable.getWrenchDrop(player); - world.setBlockToAir(x, y, z); - world.spawnEntityInWorld(new EntityItem(world, x, y, z, drop)); + if (!wrenchable.wrenchCanRemove(player)) { + event.setCanceled(true); + return; + } + wrenchableDrop = wrenchable.getWrenchDrop(player); + wrenchableDropRate = wrenchable.getWrenchDropRate(); + } + if (block instanceof AEBaseTileBlock aeBaseTileBlock) { + if (LastEventFromThis) { + return; + } + final boolean sneak = player.isSneaking(); + try { + LastEventFromThis = true; + player.setSneaking(true); + final int sideHit = player.rayTrace(5, 1.0f).sideHit; + if (tile instanceof IPartHost) { + if (sneak && PartPlacement.place( + player.getHeldItem(), + x, + y, + z, + sideHit, + player, + player.worldObj, + PartPlacement.PlaceType.INTERACT_FIRST_PASS, + 0)) { + event.setCanceled(true); + } + return; + } + if (aeBaseTileBlock.onBlockActivated(event.world, x, y, z, player, sideHit, x, y, z)) { + event.setCanceled(true); + } + } finally { + LastEventFromThis = false; + player.setSneaking(sneak); + } } } @Override - public String getToolTypeName() { - return "wrench"; - } + public int convertBlockDrops(List<ItemStack> drops, ItemStack Stack, EntityPlayer player, Block block, int x, int y, + int z, byte metaData, int fortune, boolean silkTouch, BlockEvent.HarvestDropsEvent event) { + ItemStack drop = null; + int modified = 0; + if (wrenchableDrop != null) { + drop = wrenchableDrop; + wrenchableDrop = null; + modified = wrenchableDropRate == 1.0f ? 3 : 10; + wrenchableDropRate = 0.0f; + } else if (block == Blocks.bookshelf || block == Blocks.ender_chest) { + drop = new ItemStack(block); + modified = 1; + } - @Override - public byte getMaxMode() { - return 2; + if (drop != null) { + event.dropChance = 1.0f; + drops.clear(); + drops.add(drop); + } + return modified; } } |