From 7b2930d5e5d93c981d53b8436cbbd5258777c52f Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 24 Dec 2018 12:11:28 -0600 Subject: [PATCH] Bot Breaking that is moderately cursed DMCA gang --- src/api/java/baritone/api/Settings.java | 4 - .../baritone/api/utils/IPlayerContext.java | 4 +- .../baritone/api/utils/IPlayerController.java | 6 +- .../java/baritone/bot/BotPlayerContext.java | 6 - .../bot/handler/BotNetHandlerPlayClient.java | 6 +- .../bot/spec/BotPlayerController.java | 223 +++++++++++++++++- .../java/baritone/utils/BlockBreakHelper.java | 10 - .../utils/player/PrimaryPlayerController.java | 11 +- 8 files changed, 229 insertions(+), 41 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index c2d1e3c0..0093c3ce 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -435,10 +435,6 @@ public class Settings { /** * {@code true}: can mine blocks when in inventory, chat, or tabbed away in ESC menu - *

- * {@code false}: works on cosmic prisons - *

- * LOL */ public Setting leftClickWorkaround = new Setting<>(true); diff --git a/src/api/java/baritone/api/utils/IPlayerContext.java b/src/api/java/baritone/api/utils/IPlayerContext.java index 83040ab5..3fdca1fa 100644 --- a/src/api/java/baritone/api/utils/IPlayerContext.java +++ b/src/api/java/baritone/api/utils/IPlayerContext.java @@ -42,7 +42,9 @@ public interface IPlayerContext { IWorldData worldData(); - RayTraceResult objectMouseOver(); + default RayTraceResult objectMouseOver() { + return playerController().objectMouseOver(); + } default BetterBlockPos playerFeet() { // TODO find a better way to deal with soul sand!!!!! diff --git a/src/api/java/baritone/api/utils/IPlayerController.java b/src/api/java/baritone/api/utils/IPlayerController.java index 969431b1..2b3c7fc5 100644 --- a/src/api/java/baritone/api/utils/IPlayerController.java +++ b/src/api/java/baritone/api/utils/IPlayerController.java @@ -17,12 +17,12 @@ package baritone.api.utils; -import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.ClickType; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.GameType; /** @@ -31,8 +31,6 @@ import net.minecraft.world.GameType; */ public interface IPlayerController { - boolean clickBlock(BlockPos pos, EnumFacing side); - boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side); void resetBlockRemoving(); @@ -43,6 +41,8 @@ public interface IPlayerController { GameType getGameType(); + RayTraceResult objectMouseOver(); + default double getBlockReachDistance() { return this.getGameType().isCreative() ? 5.0F : 4.5F; } diff --git a/src/main/java/baritone/bot/BotPlayerContext.java b/src/main/java/baritone/bot/BotPlayerContext.java index 87d90dc8..a2fcae03 100644 --- a/src/main/java/baritone/bot/BotPlayerContext.java +++ b/src/main/java/baritone/bot/BotPlayerContext.java @@ -64,10 +64,4 @@ public class BotPlayerContext implements IPlayerContext { public IWorldData worldData() { return bot.getBaritone().getWorldProvider().getCurrentWorld(); } - - @Override - public RayTraceResult objectMouseOver() { - // TODO-yeet lol fix this - return Minecraft.getMinecraft().objectMouseOver; - } } diff --git a/src/main/java/baritone/bot/handler/BotNetHandlerPlayClient.java b/src/main/java/baritone/bot/handler/BotNetHandlerPlayClient.java index ffa408e7..ceb1362c 100644 --- a/src/main/java/baritone/bot/handler/BotNetHandlerPlayClient.java +++ b/src/main/java/baritone/bot/handler/BotNetHandlerPlayClient.java @@ -358,6 +358,7 @@ public class BotNetHandlerPlayClient extends NetHandlerPlayClient { this.playerController = new BotPlayerController(this.user); this.world = this.user.getManager().getWorldProvider().getWorld(packetIn.getDimension()); this.player = new EntityBot(this.user, (Minecraft) this.client, this.world, this, new StatisticsManager(), new RecipeBookClient()); + this.user.onWorldLoad(this.world, this.player, this.playerController); this.player.preparePlayerToSpawn(); this.world.spawnEntity(this.player); this.player.setEntityId(packetIn.getPlayerId()); @@ -370,8 +371,6 @@ public class BotNetHandlerPlayClient extends NetHandlerPlayClient { this.world.registerBot(packetIn.getPlayerId(), this.player); - this.user.onWorldLoad(this.world, this.player, this.playerController); - Helper.HELPER.logDirect("Initialized Player and World"); } @@ -479,6 +478,7 @@ public class BotNetHandlerPlayClient extends NetHandlerPlayClient { EntityBot prev = this.player; this.player = new EntityBot(this.user, (Minecraft) this.client, this.world, this, prev.getStatFileWriter(), prev.getRecipeBook()); + this.user.onWorldLoad(this.world, this.player, this.playerController); // noinspection ConstantConditions this.player.getDataManager().setEntryValues(prev.getDataManager().getAll()); this.player.preparePlayerToSpawn(); @@ -487,8 +487,6 @@ public class BotNetHandlerPlayClient extends NetHandlerPlayClient { this.player.dimension = packetIn.getDimensionID(); this.player.setServerBrand(prev.getServerBrand()); this.playerController.setGameType(packetIn.getGameType()); - - this.user.onWorldLoad(this.world, this.player, this.playerController); } @Override diff --git a/src/main/java/baritone/bot/spec/BotPlayerController.java b/src/main/java/baritone/bot/spec/BotPlayerController.java index fff38f9c..7a598527 100644 --- a/src/main/java/baritone/bot/spec/BotPlayerController.java +++ b/src/main/java/baritone/bot/spec/BotPlayerController.java @@ -19,13 +19,26 @@ package baritone.bot.spec; import baritone.api.utils.IPlayerController; import baritone.bot.IBaritoneUser; +import net.minecraft.block.Block; +import net.minecraft.block.BlockCommandBlock; +import net.minecraft.block.BlockStructure; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; import net.minecraft.inventory.ClickType; import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; import net.minecraft.network.play.client.CPacketClickWindow; +import net.minecraft.network.play.client.CPacketHeldItemChange; +import net.minecraft.network.play.client.CPacketPlayerDigging; import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.GameType; +import net.minecraft.world.World; /** * @author Brady @@ -35,29 +48,81 @@ public class BotPlayerController implements IPlayerController { private final IBaritoneUser user; private GameType gameType; + private RayTraceResult objectMouseOver; + + private BlockPos currentBlock; + private ItemStack currentHittingItem; + private boolean hittingBlock; + private float blockDamage; + private int blockHitDelay; + private int heldItemServer; public BotPlayerController(IBaritoneUser user) { this.user = user; - } - - @Override - public boolean clickBlock(BlockPos pos, EnumFacing side) { - return false; + this.currentHittingItem = ItemStack.EMPTY; } @Override public boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side) { - return false; + this.syncHeldItem(); + + EntityBot player = this.user.getEntity(); + World world = player.world; + + if (this.blockHitDelay > 0) { + this.blockHitDelay--; + return true; + } + + if (this.gameType.isCreative() && world.getWorldBorder().contains(pos)) { + player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.START_DESTROY_BLOCK, pos, side)); + handleCreativeBreak(pos, side); + this.blockHitDelay = 5; + return true; + } + + if (!this.isHittingPosition(pos)) { + return this.clickBlock(pos, side); + } + + IBlockState state = world.getBlockState(pos); + + if (state.getMaterial() == Material.AIR) { + this.hittingBlock = false; + return false; + } + + this.blockDamage += state.getPlayerRelativeBlockHardness(player, world, pos); + + if (this.blockDamage >= 1.0F) { + this.hittingBlock = false; + this.blockDamage = 0.0F; + this.blockHitDelay = 5; + + player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.STOP_DESTROY_BLOCK, pos, side)); + this.handleBreak(pos); + } + + world.sendBlockBreakProgress(player.getEntityId(), this.currentBlock, (int) (this.blockDamage * 10.0F) - 1); + return true; } @Override public void resetBlockRemoving() { - + if (this.hittingBlock) { + this.hittingBlock = false; + this.blockDamage = 0.0F; + this.user.getEntity().resetCooldown(); + this.user.getEntity().connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.ABORT_DESTROY_BLOCK, this.currentBlock, EnumFacing.DOWN)); + } } @Override public ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player) { - return null; + short transactionID = player.openContainer.getNextTransactionID(player.inventory); + ItemStack stack = player.openContainer.slotClick(slotId, mouseButton, type, player); + this.user.getEntity().connection.sendPacket(new CPacketClickWindow(windowId, slotId, mouseButton, type, stack, transactionID)); + return stack; } @Override @@ -70,4 +135,146 @@ public class BotPlayerController implements IPlayerController { public GameType getGameType() { return this.gameType; } + + @Override + public RayTraceResult objectMouseOver() { + Entity entity = this.user.getEntity(); + + if (entity != null) { + double blockReachDistance = getBlockReachDistance(); + this.objectMouseOver = entity.rayTrace(blockReachDistance, 1.0F); + + // TODO: Entity collision + // This doesn't matter atm because the bot worlds don't even contain entities + } + + return this.objectMouseOver; + } + + private boolean clickBlock(BlockPos pos, EnumFacing side) { + EntityBot player = this.user.getEntity(); + World world = player.world; + + if (!canBreak(player, pos)) { + return false; + } + + if (this.gameType.isCreative()) { + player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.START_DESTROY_BLOCK, pos, side)); + handleCreativeBreak(pos, side); + this.blockHitDelay = 5; + } else if (!this.hittingBlock || !this.isHittingPosition(pos)) { + if (this.hittingBlock) { + player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.ABORT_DESTROY_BLOCK, this.currentBlock, side)); + } + + IBlockState state = world.getBlockState(pos); + player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.START_DESTROY_BLOCK, pos, side)); + + if (state.getMaterial() != Material.AIR) { + if (this.blockDamage == 0.0F) { + state.getBlock().onBlockClicked(world, pos, player); + } + if (state.getPlayerRelativeBlockHardness(player, player.world, pos) >= 1.0F) { + this.handleBreak(pos); + } + } else { + this.hittingBlock = true; + this.currentBlock = pos; + this.blockDamage = 0.0F; + this.currentHittingItem = player.getHeldItemMainhand(); + world.sendBlockBreakProgress(player.getEntityId(), this.currentBlock, (int) (this.blockDamage * 10.0F) - 1); + } + } + + return true; + } + + private void handleBreak(BlockPos pos) { + EntityBot player = this.user.getEntity(); + World world = player.world; + + if (this.gameType.isCreative() && !player.getHeldItemMainhand().isEmpty() && player.getHeldItemMainhand().getItem() instanceof ItemSword) { + return; + } + + IBlockState state = world.getBlockState(pos); + Block block = state.getBlock(); + + if ((block instanceof BlockCommandBlock || block instanceof BlockStructure) && !player.canUseCommandBlock()) { + return; + } + + if (state.getMaterial() == Material.AIR) { + return; + } + + block.onBlockHarvested(world, pos, state, player); + + if (world.setBlockState(pos, Blocks.AIR.getDefaultState(), 11)) { + block.onPlayerDestroy(world, pos, state); + } + + this.currentBlock = new BlockPos(this.currentBlock.getX(), -1, this.currentBlock.getZ()); + + if (!this.gameType.isCreative()) { + ItemStack stack = player.getHeldItemMainhand(); + + if (!stack.isEmpty()) { + stack.onBlockDestroyed(world, state, pos, player); + + if (stack.isEmpty()) { + player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY); + } + } + } + } + + private void handleCreativeBreak(BlockPos pos, EnumFacing side) { + EntityPlayer player = this.user.getEntity(); + if (!player.world.extinguishFire(player, pos, side)) { + this.handleBreak(pos); + } + } + + private boolean canBreak(EntityPlayer player, BlockPos pos) { + if (!player.world.getWorldBorder().contains(pos)) { + return false; + } + + if (this.gameType.hasLimitedInteractions()) { + if (this.gameType == GameType.SPECTATOR) { + return false; + } + + if (!player.isAllowEdit()) { + ItemStack stack = player.getHeldItemMainhand(); + + return !stack.isEmpty() && stack.canDestroy(player.world.getBlockState(pos).getBlock()); + } + } + return true; + } + + private boolean isHittingPosition(BlockPos pos) { + ItemStack stack = this.user.getEntity().getHeldItemMainhand(); + boolean itemUnchanged = this.currentHittingItem.isEmpty() && stack.isEmpty(); + + if (!this.currentHittingItem.isEmpty() && !stack.isEmpty()) { + itemUnchanged = stack.getItem() == this.currentHittingItem.getItem() + && ItemStack.areItemStackTagsEqual(stack, this.currentHittingItem) + && (stack.isItemStackDamageable() || stack.getMetadata() == this.currentHittingItem.getMetadata()); + } + + return pos.equals(this.currentBlock) && itemUnchanged; + } + + private void syncHeldItem() { + int heldItemClient = this.user.getEntity().inventory.currentItem; + + if (heldItemClient != this.heldItemServer) { + this.heldItemServer = heldItemClient; + this.user.getEntity().connection.sendPacket(new CPacketHeldItemChange(this.heldItemServer)); + } + } } diff --git a/src/main/java/baritone/utils/BlockBreakHelper.java b/src/main/java/baritone/utils/BlockBreakHelper.java index 9f5b970d..36f31c6d 100644 --- a/src/main/java/baritone/utils/BlockBreakHelper.java +++ b/src/main/java/baritone/utils/BlockBreakHelper.java @@ -31,11 +31,6 @@ import net.minecraft.util.math.RayTraceResult; */ public final class BlockBreakHelper implements Helper { - /** - * The last block that we tried to break, if this value changes - * between attempts, then we re-initialize the breaking process. - */ - private BlockPos lastBlock; private boolean didBreakLastTick; private IPlayerContext playerContext; @@ -45,13 +40,9 @@ public final class BlockBreakHelper implements Helper { } public void tryBreakBlock(BlockPos pos, EnumFacing side) { - if (!pos.equals(lastBlock)) { - playerContext.playerController().clickBlock(pos, side); - } if (playerContext.playerController().onPlayerDamageBlock(pos, side)) { playerContext.player().swingArm(EnumHand.MAIN_HAND); } - lastBlock = pos; } public void stopBreakingBlock() { @@ -59,7 +50,6 @@ public final class BlockBreakHelper implements Helper { if (playerContext.player() != null) { playerContext.playerController().resetBlockRemoving(); } - lastBlock = null; } private boolean fakeBreak() { diff --git a/src/main/java/baritone/utils/player/PrimaryPlayerController.java b/src/main/java/baritone/utils/player/PrimaryPlayerController.java index fa4ced9d..b4ff09e7 100644 --- a/src/main/java/baritone/utils/player/PrimaryPlayerController.java +++ b/src/main/java/baritone/utils/player/PrimaryPlayerController.java @@ -24,6 +24,7 @@ import net.minecraft.inventory.ClickType; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.GameType; /** @@ -34,11 +35,6 @@ public enum PrimaryPlayerController implements IPlayerController, Helper { INSTANCE; - @Override - public boolean clickBlock(BlockPos pos, EnumFacing side) { - return mc.playerController.clickBlock(pos, side); - } - @Override public boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side) { return mc.playerController.onPlayerDamageBlock(pos, side); @@ -63,4 +59,9 @@ public enum PrimaryPlayerController implements IPlayerController, Helper { public GameType getGameType() { return mc.playerController.getCurrentGameType(); } + + @Override + public RayTraceResult objectMouseOver() { + return mc.objectMouseOver; + } }