0
0
mirror of https://github.com/Wurst-Imperium/Wurst7.git synced 2024-09-20 01:12:13 +02:00

Merge tag 'v7.35.1' into 1.19.2

This commit is contained in:
Alexander01998 2023-06-12 16:17:07 +02:00
commit 7901d3a212
9 changed files with 454 additions and 496 deletions

View File

@ -12,7 +12,7 @@ loader_version=0.14.21
fabric_version=0.76.0+1.19.2
# Mod Properties
mod_version = v7.35-MC1.19.2
mod_version = v7.35.1-MC1.19.2
maven_group = net.wurstclient
archives_base_name = Wurst-Client

View File

@ -58,7 +58,7 @@ public enum WurstClient
public static MinecraftClient MC;
public static IMinecraftClient IMC;
public static final String VERSION = "7.35";
public static final String VERSION = "7.35.1";
public static final String MC_VERSION = "1.19.2";
private WurstAnalytics analytics;

View File

@ -11,45 +11,31 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.block.*;
import net.minecraft.client.gl.VertexBuffer;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.BufferBuilder.BuiltBuffer;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.Shader;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.wurstclient.Category;
import net.wurstclient.SearchTags;
import net.wurstclient.WurstClient;
import net.wurstclient.events.RenderListener;
import net.wurstclient.events.UpdateListener;
import net.wurstclient.hack.Hack;
import net.wurstclient.hacks.autofarm.AutoFarmRenderer;
import net.wurstclient.settings.CheckboxSetting;
import net.wurstclient.settings.SliderSetting;
import net.wurstclient.settings.SliderSetting.ValueDisplay;
import net.wurstclient.util.BlockBreaker;
import net.wurstclient.util.BlockPlacer;
import net.wurstclient.util.BlockPlacer.BlockPlacingParams;
import net.wurstclient.util.BlockUtils;
import net.wurstclient.util.RenderUtils;
import net.wurstclient.util.InventoryUtils;
import net.wurstclient.util.OverlayRenderer;
import net.wurstclient.util.RotationUtils;
@SearchTags({"auto farm", "AutoHarvest", "auto harvest"})
@ -62,16 +48,25 @@ public final class AutoFarmHack extends Hack
private final CheckboxSetting replant =
new CheckboxSetting("Replant", true);
private final HashMap<Block, Item> seeds = new HashMap<>();
{
seeds.put(Blocks.WHEAT, Items.WHEAT_SEEDS);
seeds.put(Blocks.CARROTS, Items.CARROT);
seeds.put(Blocks.POTATOES, Items.POTATO);
seeds.put(Blocks.BEETROOTS, Items.BEETROOT_SEEDS);
seeds.put(Blocks.PUMPKIN_STEM, Items.PUMPKIN_SEEDS);
seeds.put(Blocks.MELON_STEM, Items.MELON_SEEDS);
seeds.put(Blocks.NETHER_WART, Items.NETHER_WART);
seeds.put(Blocks.COCOA, Items.COCOA_BEANS);
}
private final HashMap<BlockPos, Item> plants = new HashMap<>();
private final ArrayDeque<Set<BlockPos>> prevBlocks = new ArrayDeque<>();
private BlockPos currentBlock;
private float progress;
private float prevProgress;
private BlockPos currentlyHarvesting;
private VertexBuffer greenBuffer;
private VertexBuffer cyanBuffer;
private VertexBuffer redBuffer;
private final AutoFarmRenderer renderer = new AutoFarmRenderer();
private final OverlayRenderer overlay = new OverlayRenderer();
private boolean busy;
@ -99,180 +94,103 @@ public final class AutoFarmHack extends Hack
EVENTS.remove(UpdateListener.class, this);
EVENTS.remove(RenderListener.class, this);
if(currentBlock != null)
if(currentlyHarvesting != null)
{
IMC.getInteractionManager().setBreakingBlock(true);
MC.interactionManager.cancelBlockBreaking();
currentBlock = null;
currentlyHarvesting = null;
}
prevBlocks.clear();
overlay.resetProgress();
busy = false;
Stream.of(greenBuffer, cyanBuffer, redBuffer).filter(Objects::nonNull)
.forEach(VertexBuffer::close);
greenBuffer = cyanBuffer = redBuffer = null;
renderer.reset();
}
@Override
public void onUpdate()
{
currentBlock = null;
currentlyHarvesting = null;
Vec3d eyesVec = RotationUtils.getEyesPos().subtract(0.5, 0.5, 0.5);
BlockPos eyesBlock = new BlockPos(RotationUtils.getEyesPos());
double rangeSq = range.getValueSq();
int blockRange = range.getValueCeil();
List<BlockPos> blocks = getBlockStream(eyesBlock, blockRange)
// get nearby, non-empty blocks
ArrayList<BlockPos> blocks = BlockUtils
.getAllInBoxStream(eyesBlock, blockRange)
.filter(pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)) <= rangeSq)
.filter(BlockUtils::canBeClicked).collect(Collectors.toList());
.filter(BlockUtils::canBeClicked)
.collect(Collectors.toCollection(ArrayList::new));
registerPlants(blocks);
// check for any new plants and add them to the map
updatePlants(blocks);
List<BlockPos> blocksToHarvest = new ArrayList<>();
List<BlockPos> blocksToReplant = new ArrayList<>();
ArrayList<BlockPos> blocksToHarvest = new ArrayList<>();
ArrayList<BlockPos> blocksToReplant = new ArrayList<>();
// don't place or break any blocks while Freecam is enabled
if(!WURST.getHax().freecamHack.isEnabled())
{
// check which of the nearby blocks can be harvested
blocksToHarvest = getBlocksToHarvest(eyesVec, blocks);
// do a new search to find empty blocks that can be replanted
if(replant.isChecked())
blocksToReplant =
getBlocksToReplant(eyesVec, eyesBlock, rangeSq, blockRange);
}
boolean replanting = false;
while(!blocksToReplant.isEmpty())
{
BlockPos pos = blocksToReplant.get(0);
Item neededItem = plants.get(pos);
if(tryToReplant(pos, neededItem))
{
replanting = true;
break;
}
blocksToReplant.removeIf(p -> plants.get(p) == neededItem);
}
// first, try to replant
boolean replanting = replant(blocksToReplant);
// if we can't replant, harvest instead
if(!replanting)
harvest(blocksToHarvest);
busy = !blocksToHarvest.isEmpty() || !blocksToReplant.isEmpty();
updateVertexBuffers(blocksToHarvest, blocksToReplant);
}
private List<BlockPos> getBlocksToHarvest(Vec3d eyesVec,
List<BlockPos> blocks)
{
return blocks.parallelStream().filter(this::shouldBeHarvested)
.sorted(Comparator.comparingDouble(
pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos))))
.collect(Collectors.toList());
}
private List<BlockPos> getBlocksToReplant(Vec3d eyesVec, BlockPos eyesBlock,
double rangeSq, int blockRange)
{
return getBlockStream(eyesBlock, blockRange)
.filter(pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)) <= rangeSq)
.filter(
pos -> BlockUtils.getState(pos).getMaterial().isReplaceable())
.filter(pos -> plants.containsKey(pos)).filter(this::canBeReplanted)
.sorted(Comparator.comparingDouble(
pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos))))
.collect(Collectors.toList());
// upate busy state
busy = replanting || currentlyHarvesting != null;
// update renderer
renderer.updateVertexBuffers(blocksToHarvest, plants.keySet(),
blocksToReplant);
}
@Override
public void onRender(MatrixStack matrixStack, float partialTicks)
{
if(WurstClient.MC.getBlockEntityRenderDispatcher().camera == null)
return;
// GL settings
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_DEPTH_TEST);
matrixStack.push();
BlockPos camPos = RenderUtils.getCameraBlockPos();
int regionX = (camPos.getX() >> 9) * 512;
int regionZ = (camPos.getZ() >> 9) * 512;
RenderUtils.applyRegionalRenderOffset(matrixStack, regionX, regionZ);
RenderSystem.setShader(GameRenderer::getPositionShader);
Matrix4f viewMatrix = matrixStack.peek().getPositionMatrix();
Matrix4f projMatrix = RenderSystem.getProjectionMatrix();
Shader shader = RenderSystem.getShader();
if(greenBuffer != null)
{
RenderSystem.setShaderColor(0, 1, 0, 0.5F);
greenBuffer.bind();
greenBuffer.draw(viewMatrix, projMatrix, shader);
VertexBuffer.unbind();
}
if(cyanBuffer != null)
{
RenderSystem.setShaderColor(0, 1, 1, 0.5F);
cyanBuffer.bind();
cyanBuffer.draw(viewMatrix, projMatrix, shader);
VertexBuffer.unbind();
}
if(redBuffer != null)
{
RenderSystem.setShaderColor(1, 0, 0, 0.5F);
redBuffer.bind();
redBuffer.draw(viewMatrix, projMatrix, shader);
VertexBuffer.unbind();
}
if(currentBlock != null)
{
matrixStack.push();
Box box = new Box(BlockPos.ORIGIN);
float p = prevProgress + (progress - prevProgress) * partialTicks;
float red = p * 2F;
float green = 2 - red;
matrixStack.translate(currentBlock.getX() - regionX,
currentBlock.getY(), currentBlock.getZ() - regionZ);
if(p < 1)
{
matrixStack.translate(0.5, 0.5, 0.5);
matrixStack.scale(p, p, p);
matrixStack.translate(-0.5, -0.5, -0.5);
}
RenderSystem.setShaderColor(red, green, 0, 0.25F);
RenderUtils.drawSolidBox(box, matrixStack);
RenderSystem.setShaderColor(red, green, 0, 0.5F);
RenderUtils.drawOutlinedBox(box, matrixStack);
matrixStack.pop();
}
matrixStack.pop();
// GL resets
RenderSystem.setShaderColor(1, 1, 1, 1);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDisable(GL11.GL_BLEND);
renderer.render(matrixStack);
overlay.render(matrixStack, partialTicks, currentlyHarvesting);
}
private Stream<BlockPos> getBlockStream(BlockPos center, int range)
/**
* Returns true if AutoFarm is currently harvesting or replanting something.
*/
public boolean isBusy()
{
BlockPos min = center.add(-range, -range, -range);
BlockPos max = center.add(range, range, range);
return BlockUtils.getAllInBox(min, max).stream();
return busy;
}
private void updatePlants(List<BlockPos> blocks)
{
for(BlockPos pos : blocks)
{
Item seed = seeds.get(BlockUtils.getBlock(pos));
if(seed == null)
continue;
plants.put(pos, seed);
}
}
private ArrayList<BlockPos> getBlocksToHarvest(Vec3d eyesVec,
ArrayList<BlockPos> blocks)
{
return blocks.parallelStream().filter(this::shouldBeHarvested)
.sorted(Comparator.comparingDouble(
pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos))))
.collect(Collectors.toCollection(ArrayList::new));
}
private boolean shouldBeHarvested(BlockPos pos)
@ -282,6 +200,13 @@ public final class AutoFarmHack extends Hack
if(block instanceof CropBlock)
return ((CropBlock)block).isMature(state);
if(block instanceof NetherWartBlock)
return state.get(NetherWartBlock.AGE) >= 3;
if(block instanceof CocoaBlock)
return state.get(CocoaBlock.AGE) >= 2;
if(block instanceof GourdBlock)
return true;
if(block instanceof SugarCaneBlock)
@ -295,33 +220,25 @@ public final class AutoFarmHack extends Hack
return BlockUtils.getBlock(pos.down()) instanceof KelpPlantBlock
&& !(BlockUtils
.getBlock(pos.down(2)) instanceof KelpPlantBlock);
if(block instanceof NetherWartBlock)
return state.get(NetherWartBlock.AGE) >= 3;
if(block instanceof BambooBlock)
return BlockUtils.getBlock(pos.down()) instanceof BambooBlock
&& !(BlockUtils.getBlock(pos.down(2)) instanceof BambooBlock);
if(block instanceof CocoaBlock)
return state.get(CocoaBlock.AGE) >= 2;
return false;
}
private void registerPlants(List<BlockPos> blocks)
private ArrayList<BlockPos> getBlocksToReplant(Vec3d eyesVec,
BlockPos eyesBlock, double rangeSq, int blockRange)
{
HashMap<Block, Item> seeds = new HashMap<>();
seeds.put(Blocks.WHEAT, Items.WHEAT_SEEDS);
seeds.put(Blocks.CARROTS, Items.CARROT);
seeds.put(Blocks.POTATOES, Items.POTATO);
seeds.put(Blocks.BEETROOTS, Items.BEETROOT_SEEDS);
seeds.put(Blocks.PUMPKIN_STEM, Items.PUMPKIN_SEEDS);
seeds.put(Blocks.MELON_STEM, Items.MELON_SEEDS);
seeds.put(Blocks.NETHER_WART, Items.NETHER_WART);
seeds.put(Blocks.COCOA, Items.COCOA_BEANS);
plants.putAll(blocks.parallelStream()
.filter(pos -> seeds.containsKey(BlockUtils.getBlock(pos)))
.collect(Collectors.toMap(pos -> pos,
pos -> seeds.get(BlockUtils.getBlock(pos)))));
return BlockUtils.getAllInBoxStream(eyesBlock, blockRange)
.filter(pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)) <= rangeSq)
.filter(
pos -> BlockUtils.getState(pos).getMaterial().isReplaceable())
.filter(pos -> plants.containsKey(pos)).filter(this::canBeReplanted)
.sorted(Comparator.comparingDouble(
pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos))))
.collect(Collectors.toCollection(ArrayList::new));
}
private boolean canBeReplanted(BlockPos pos)
@ -345,255 +262,109 @@ public final class AutoFarmHack extends Hack
return false;
}
private boolean tryToReplant(BlockPos pos, Item neededItem)
private boolean replant(List<BlockPos> blocksToReplant)
{
ClientPlayerEntity player = MC.player;
ItemStack heldItem = player.getMainHandStack();
if(!heldItem.isEmpty() && heldItem.getItem() == neededItem)
{
placeBlockSimple(pos);
return IMC.getItemUseCooldown() <= 0;
}
for(int slot = 0; slot < 36; slot++)
{
if(slot == player.getInventory().selectedSlot)
continue;
ItemStack stack = player.getInventory().getStack(slot);
if(stack.isEmpty() || stack.getItem() != neededItem)
continue;
if(slot < 9)
player.getInventory().selectedSlot = slot;
else if(player.getInventory().getEmptySlot() < 9)
IMC.getInteractionManager().windowClick_QUICK_MOVE(slot);
else if(player.getInventory().getEmptySlot() != -1)
{
IMC.getInteractionManager().windowClick_QUICK_MOVE(
player.getInventory().selectedSlot + 36);
IMC.getInteractionManager().windowClick_QUICK_MOVE(slot);
}else
{
IMC.getInteractionManager().windowClick_PICKUP(
player.getInventory().selectedSlot + 36);
IMC.getInteractionManager().windowClick_PICKUP(slot);
IMC.getInteractionManager().windowClick_PICKUP(
player.getInventory().selectedSlot + 36);
}
return true;
}
return false;
}
private void placeBlockSimple(BlockPos pos)
{
Direction side = null;
Direction[] sides = Direction.values();
Vec3d eyesPos = RotationUtils.getEyesPos();
Vec3d posVec = Vec3d.ofCenter(pos);
double distanceSqPosVec = eyesPos.squaredDistanceTo(posVec);
Vec3d[] hitVecs = new Vec3d[sides.length];
for(int i = 0; i < sides.length; i++)
hitVecs[i] =
posVec.add(Vec3d.of(sides[i].getVector()).multiply(0.5));
for(int i = 0; i < sides.length; i++)
{
// check if neighbor can be right clicked
BlockPos neighbor = pos.offset(sides[i]);
if(!BlockUtils.canBeClicked(neighbor))
continue;
// check line of sight
BlockState neighborState = BlockUtils.getState(neighbor);
VoxelShape neighborShape =
neighborState.getOutlineShape(MC.world, neighbor);
if(MC.world.raycastBlock(eyesPos, hitVecs[i], neighbor,
neighborShape, neighborState) != null)
continue;
side = sides[i];
break;
}
if(side == null)
for(int i = 0; i < sides.length; i++)
{
// check if neighbor can be right clicked
if(!BlockUtils.canBeClicked(pos.offset(sides[i])))
continue;
// check if side is facing away from player
if(distanceSqPosVec > eyesPos.squaredDistanceTo(hitVecs[i]))
continue;
side = sides[i];
break;
}
if(side == null)
return;
Vec3d hitVec = hitVecs[side.ordinal()];
// face block
WURST.getRotationFaker().faceVectorPacket(hitVec);
if(RotationUtils.getAngleToLastReportedLookVec(hitVec) > 1)
return;
// check timer
// check cooldown
if(IMC.getItemUseCooldown() > 0)
return;
return false;
// place block
IMC.getInteractionManager().rightClickBlock(pos.offset(side),
side.getOpposite(), hitVec);
// check if already holding one of the seeds needed for blocksToReplant
Optional<Item> heldSeed = blocksToReplant.stream().map(plants::get)
.distinct().filter(item -> MC.player.isHolding(item)).findFirst();
// swing arm
MC.player.networkHandler
.sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND));
// if so, try to replant the blocks that need that seed
if(heldSeed.isPresent())
{
// get the seed and the hand that is holding it
Item item = heldSeed.get();
Hand hand = MC.player.getMainHandStack().isOf(item) ? Hand.MAIN_HAND
: Hand.OFF_HAND;
// filter out blocks that need a different seed
ArrayList<BlockPos> blocksToReplantWithHeldSeed =
blocksToReplant.stream().filter(pos -> plants.get(pos) == item)
.collect(Collectors.toCollection(ArrayList::new));
for(BlockPos pos : blocksToReplantWithHeldSeed)
{
// skip over blocks that we can't reach
BlockPlacingParams params =
BlockPlacer.getBlockPlacingParams(pos);
if(params == null || params.distanceSq() > range.getValueSq())
continue;
// face block
WURST.getRotationFaker().faceVectorPacket(params.hitVec());
// place seed
ActionResult result = MC.interactionManager
.interactBlock(MC.player, hand, params.toHitResult());
// swing arm
if(result.isAccepted() && result.shouldSwingHand())
MC.player.networkHandler
.sendPacket(new HandSwingC2SPacket(hand));
// reset cooldown
IMC.setItemUseCooldown(4);
return true;
}
}
// reset timer
IMC.setItemUseCooldown(4);
// otherwise, find a block that we can reach and have seeds for
for(BlockPos pos : blocksToReplant)
{
// skip over blocks that we can't reach
BlockPlacingParams params = BlockPlacer.getBlockPlacingParams(pos);
if(params == null || params.distanceSq() > range.getValueSq())
continue;
// try to select the seed (returns false if we don't have it)
Item item = plants.get(pos);
if(InventoryUtils.selectItem(item))
return true;
}
// if we couldn't replant anything, return false
return false;
}
private void harvest(List<BlockPos> blocksToHarvest)
{
if(MC.player.getAbilities().creativeMode)
{
Stream<BlockPos> stream3 = blocksToHarvest.parallelStream();
Stream<BlockPos> stream = blocksToHarvest.parallelStream();
for(Set<BlockPos> set : prevBlocks)
stream3 = stream3.filter(pos -> !set.contains(pos));
List<BlockPos> blocksToHarvest2 =
stream3.collect(Collectors.toList());
stream = stream.filter(pos -> !set.contains(pos));
List<BlockPos> filteredBlocks = stream.collect(Collectors.toList());
prevBlocks.addLast(new HashSet<>(blocksToHarvest2));
prevBlocks.addLast(new HashSet<>(filteredBlocks));
while(prevBlocks.size() > 5)
prevBlocks.removeFirst();
if(!blocksToHarvest2.isEmpty())
currentBlock = blocksToHarvest2.get(0);
if(!filteredBlocks.isEmpty())
currentlyHarvesting = filteredBlocks.get(0);
MC.interactionManager.cancelBlockBreaking();
progress = 1;
prevProgress = 1;
BlockBreaker.breakBlocksWithPacketSpam(blocksToHarvest2);
overlay.resetProgress();
BlockBreaker.breakBlocksWithPacketSpam(filteredBlocks);
return;
}
for(BlockPos pos : blocksToHarvest)
if(BlockBreaker.breakOneBlock(pos))
{
currentBlock = pos;
currentlyHarvesting = pos;
break;
}
if(currentBlock == null)
if(currentlyHarvesting == null)
MC.interactionManager.cancelBlockBreaking();
if(currentBlock != null && BlockUtils.getHardness(currentBlock) < 1)
{
prevProgress = progress;
progress = IMC.getInteractionManager().getCurrentBreakingProgress();
if(progress < prevProgress)
prevProgress = progress;
}else
{
progress = 1;
prevProgress = 1;
}
}
private void updateVertexBuffers(List<BlockPos> blocksToHarvest,
List<BlockPos> blocksToReplant)
{
if(WurstClient.MC.getBlockEntityRenderDispatcher().camera == null)
return;
Tessellator tessellator = RenderSystem.renderThreadTesselator();
BufferBuilder bufferBuilder = tessellator.getBuffer();
BlockPos camPos = RenderUtils.getCameraBlockPos();
int regionX = (camPos.getX() >> 9) * 512;
int regionZ = (camPos.getZ() >> 9) * 512;
if(greenBuffer != null)
greenBuffer.close();
greenBuffer = new VertexBuffer();
bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES,
VertexFormats.POSITION);
double boxMin = 1 / 16.0;
double boxMax = 15 / 16.0;
Box box = new Box(boxMin, boxMin, boxMin, boxMax, boxMax, boxMax);
for(BlockPos pos : blocksToHarvest)
{
Box renderBox = box.offset(pos).offset(-regionX, 0, -regionZ);
RenderUtils.drawOutlinedBox(renderBox, bufferBuilder);
}
BuiltBuffer buffer = bufferBuilder.end();
greenBuffer.bind();
greenBuffer.upload(buffer);
VertexBuffer.unbind();
if(cyanBuffer != null)
cyanBuffer.close();
cyanBuffer = new VertexBuffer();
bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES,
VertexFormats.POSITION);
Box node = new Box(0.25, 0.25, 0.25, 0.75, 0.75, 0.75);
for(BlockPos pos : plants.keySet())
{
Box renderNode = node.offset(pos).offset(-regionX, 0, -regionZ);
RenderUtils.drawNode(renderNode, bufferBuilder);
}
buffer = bufferBuilder.end();
cyanBuffer.bind();
cyanBuffer.upload(buffer);
VertexBuffer.unbind();
if(redBuffer != null)
redBuffer.close();
redBuffer = new VertexBuffer();
bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES,
VertexFormats.POSITION);
for(BlockPos pos : blocksToReplant)
{
Box renderBox = box.offset(pos).offset(-regionX, 0, -regionZ);
RenderUtils.drawOutlinedBox(renderBox, bufferBuilder);
}
buffer = bufferBuilder.end();
redBuffer.bind();
redBuffer.upload(buffer);
VertexBuffer.unbind();
}
/**
* Returns true if AutoFarm is currently harvesting or replanting something.
*/
public boolean isBusy()
{
return busy;
if(currentlyHarvesting != null
&& BlockUtils.getHardness(currentlyHarvesting) < 1)
overlay.updateProgress();
else
overlay.resetProgress();
}
}

View File

@ -14,16 +14,12 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.Material;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.shape.VoxelShape;
import net.wurstclient.Category;
import net.wurstclient.SearchTags;
import net.wurstclient.events.LeftClickListener;
@ -36,6 +32,8 @@ import net.wurstclient.settings.CheckboxSetting;
import net.wurstclient.settings.EnumSetting;
import net.wurstclient.settings.SliderSetting;
import net.wurstclient.settings.SliderSetting.ValueDisplay;
import net.wurstclient.util.BlockBreaker;
import net.wurstclient.util.BlockBreaker.BlockBreakingParams;
import net.wurstclient.util.BlockUtils;
import net.wurstclient.util.OverlayRenderer;
import net.wurstclient.util.RotationUtils;
@ -168,7 +166,7 @@ public final class NukerLegitHack extends Hack
}
// get valid blocks
Iterable<BlockPos> validBlocks = getValidBlocks(range.getValue(),
Iterable<BlockPos> validBlocks = getValidBlocks(range.getValueI(),
mode.getSelected().getValidator(this));
// find closest valid block
@ -193,92 +191,46 @@ public final class NukerLegitHack extends Hack
renderer.updateProgress();
}
private ArrayList<BlockPos> getValidBlocks(double range,
private ArrayList<BlockPos> getValidBlocks(int range,
Predicate<BlockPos> validator)
{
Vec3d eyesVec = RotationUtils.getEyesPos().subtract(0.5, 0.5, 0.5);
double rangeSq = Math.pow(range + 0.5, 2);
int rangeI = (int)Math.ceil(range);
Vec3d eyesVec = RotationUtils.getEyesPos();
BlockPos center = new BlockPos(eyesVec);
BlockPos center = new BlockPos(RotationUtils.getEyesPos());
BlockPos min = center.add(-rangeI, -rangeI, -rangeI);
BlockPos max = center.add(rangeI, rangeI, rangeI);
return BlockUtils.getAllInBox(min, max).stream()
.filter(pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos)) <= rangeSq)
return BlockUtils.getAllInBoxStream(center, range)
.filter(BlockUtils::canBeClicked).filter(validator)
.sorted(Comparator.comparingDouble(
pos -> eyesVec.squaredDistanceTo(Vec3d.of(pos))))
pos -> eyesVec.squaredDistanceTo(Vec3d.ofCenter(pos))))
.collect(Collectors.toCollection(ArrayList::new));
}
private boolean breakBlockExtraLegit(BlockPos pos)
{
Direction[] sides = Direction.values();
BlockState state = BlockUtils.getState(pos);
VoxelShape shape = state.getOutlineShape(MC.world, pos);
if(shape.isEmpty())
BlockBreakingParams params = BlockBreaker.getBlockBreakingParams(pos);
if(!params.lineOfSight() || params.distanceSq() > range.getValueSq())
return false;
Vec3d eyesPos = RotationUtils.getEyesPos();
Vec3d relCenter = shape.getBoundingBox().getCenter();
Vec3d center = Vec3d.of(pos).add(relCenter);
// face block
WURST.getRotationFaker().faceVectorClient(params.hitVec());
Vec3d[] hitVecs = new Vec3d[sides.length];
for(int i = 0; i < sides.length; i++)
WURST.getHax().autoToolHack.equipIfEnabled(pos);
if(!MC.interactionManager.isBreakingBlock())
MC.interactionManager.attackBlock(pos, params.side());
// if attack key is down but nothing happens,
// release it for one tick
if(MC.options.attackKey.isPressed()
&& !MC.interactionManager.isBreakingBlock())
{
Vec3i dirVec = sides[i].getVector();
Vec3d relHitVec = new Vec3d(relCenter.x * dirVec.getX(),
relCenter.y * dirVec.getY(), relCenter.z * dirVec.getZ());
hitVecs[i] = center.add(relHitVec);
}
double distanceSqToCenter = eyesPos.squaredDistanceTo(center);
for(Direction side : sides)
{
Vec3d hitVec = hitVecs[side.ordinal()];
double distanceSqHitVec = eyesPos.squaredDistanceTo(hitVec);
// check if hitVec is within range (4.25 blocks)
if(distanceSqHitVec > 18.0625)
continue;
// check if side is facing towards player
if(distanceSqHitVec >= distanceSqToCenter)
continue;
// check line of sight
if(MC.world.raycastBlock(eyesPos, hitVec, pos, shape,
state) != null)
continue;
// face block
WURST.getRotationFaker().faceVectorClient(hitVec);
if(currentBlock != null)
WURST.getHax().autoToolHack.equipIfEnabled(currentBlock);
if(!MC.interactionManager.isBreakingBlock())
MC.interactionManager.attackBlock(pos, side);
// if attack key is down but nothing happens,
// release it for one tick
if(MC.options.attackKey.isPressed()
&& !MC.interactionManager.isBreakingBlock())
{
MC.options.attackKey.setPressed(false);
return true;
}
// damage block
MC.options.attackKey.setPressed(true);
MC.options.attackKey.setPressed(false);
return true;
}
return false;
// damage block
MC.options.attackKey.setPressed(true);
return true;
}
@Override

View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2014-2023 Wurst-Imperium and contributors.
*
* This source code is subject to the terms of the GNU General Public
* License, version 3. If a copy of the GPL was not distributed with this
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
*/
package net.wurstclient.hacks.autofarm;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gl.VertexBuffer;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.BufferBuilder.BuiltBuffer;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.Shader;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vec3d;
import net.wurstclient.util.RenderUtils;
public final class AutoFarmRenderer
{
private VertexBuffer greenBuffer;
private VertexBuffer cyanBuffer;
private VertexBuffer redBuffer;
public void reset()
{
Stream.of(greenBuffer, cyanBuffer, redBuffer).filter(Objects::nonNull)
.forEach(VertexBuffer::close);
greenBuffer = cyanBuffer = redBuffer = null;
}
public void render(MatrixStack matrixStack)
{
// GL settings
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_DEPTH_TEST);
matrixStack.push();
BlockPos camPos = RenderUtils.getCameraBlockPos();
int regionX = (camPos.getX() >> 9) * 512;
int regionZ = (camPos.getZ() >> 9) * 512;
RenderUtils.applyRegionalRenderOffset(matrixStack, regionX, regionZ);
RenderSystem.setShader(GameRenderer::getPositionShader);
Matrix4f viewMatrix = matrixStack.peek().getPositionMatrix();
Matrix4f projMatrix = RenderSystem.getProjectionMatrix();
Shader shader = RenderSystem.getShader();
if(greenBuffer != null)
{
RenderSystem.setShaderColor(0, 1, 0, 0.5F);
greenBuffer.bind();
greenBuffer.draw(viewMatrix, projMatrix, shader);
VertexBuffer.unbind();
}
if(cyanBuffer != null)
{
RenderSystem.setShaderColor(0, 1, 1, 0.5F);
cyanBuffer.bind();
cyanBuffer.draw(viewMatrix, projMatrix, shader);
VertexBuffer.unbind();
}
if(redBuffer != null)
{
RenderSystem.setShaderColor(1, 0, 0, 0.5F);
redBuffer.bind();
redBuffer.draw(viewMatrix, projMatrix, shader);
VertexBuffer.unbind();
}
matrixStack.pop();
// GL resets
RenderSystem.setShaderColor(1, 1, 1, 1);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDisable(GL11.GL_BLEND);
}
public void updateVertexBuffers(List<BlockPos> blocksToHarvest,
Set<BlockPos> plants, List<BlockPos> blocksToReplant)
{
BufferBuilder bufferBuilder =
RenderSystem.renderThreadTesselator().getBuffer();
BlockPos camPos = RenderUtils.getCameraBlockPos();
int regionX = (camPos.getX() >> 9) * 512;
int regionZ = (camPos.getZ() >> 9) * 512;
Vec3d regionOffset = new Vec3d(-regionX, 0, -regionZ);
double boxMin = 1 / 16.0;
double boxMax = 15 / 16.0;
Box box = new Box(boxMin, boxMin, boxMin, boxMax, boxMax, boxMax);
Box node = new Box(0.25, 0.25, 0.25, 0.75, 0.75, 0.75);
updateGreenBuffer(blocksToHarvest, bufferBuilder, box, regionOffset);
updateCyanBuffer(plants, bufferBuilder, node, regionOffset);
updateRedBuffer(blocksToReplant, bufferBuilder, box, regionOffset);
}
private void updateGreenBuffer(List<BlockPos> blocksToHarvest,
BufferBuilder bufferBuilder, Box box, Vec3d regionOffset)
{
if(greenBuffer != null)
greenBuffer.close();
greenBuffer = new VertexBuffer();
bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES,
VertexFormats.POSITION);
for(BlockPos pos : blocksToHarvest)
{
Box renderBox = box.offset(pos).offset(regionOffset);
RenderUtils.drawOutlinedBox(renderBox, bufferBuilder);
}
BuiltBuffer buffer = bufferBuilder.end();
greenBuffer.bind();
greenBuffer.upload(buffer);
VertexBuffer.unbind();
}
private void updateCyanBuffer(Set<BlockPos> plants,
BufferBuilder bufferBuilder, Box node, Vec3d regionOffset)
{
if(cyanBuffer != null)
cyanBuffer.close();
cyanBuffer = new VertexBuffer();
bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES,
VertexFormats.POSITION);
for(BlockPos pos : plants)
{
Box renderNode = node.offset(pos).offset(regionOffset);
RenderUtils.drawNode(renderNode, bufferBuilder);
}
BuiltBuffer buffer = bufferBuilder.end();
cyanBuffer.bind();
cyanBuffer.upload(buffer);
VertexBuffer.unbind();
}
private void updateRedBuffer(List<BlockPos> blocksToReplant,
BufferBuilder bufferBuilder, Box box, Vec3d regionOffset)
{
if(redBuffer != null)
redBuffer.close();
redBuffer = new VertexBuffer();
bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES,
VertexFormats.POSITION);
for(BlockPos pos : blocksToReplant)
{
Box renderBox = box.offset(pos).offset(regionOffset);
RenderUtils.drawOutlinedBox(renderBox, bufferBuilder);
}
BuiltBuffer buffer = bufferBuilder.end();
redBuffer.bind();
redBuffer.upload(buffer);
VertexBuffer.unbind();
}
}

View File

@ -16,6 +16,7 @@ import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket.Action;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
@ -66,15 +67,17 @@ public enum BlockBreaker
return null;
Vec3d eyesPos = RotationUtils.getEyesPos();
Vec3d relCenter = shape.getBoundingBox().getCenter();
Vec3d center = Vec3d.of(pos).add(relCenter);
Box box = shape.getBoundingBox();
Vec3d halfSize = new Vec3d(box.maxX - box.minX, box.maxY - box.minY,
box.maxZ - box.minZ).multiply(0.5);
Vec3d center = Vec3d.of(pos).add(box.getCenter());
Vec3d[] hitVecs = new Vec3d[sides.length];
for(int i = 0; i < sides.length; i++)
{
Vec3i dirVec = sides[i].getVector();
Vec3d relHitVec = new Vec3d(relCenter.x * dirVec.getX(),
relCenter.y * dirVec.getY(), relCenter.z * dirVec.getZ());
Vec3d relHitVec = new Vec3d(halfSize.x * dirVec.getX(),
halfSize.y * dirVec.getY(), halfSize.z * dirVec.getZ());
hitVecs[i] = center.add(relHitVec);
}

View File

@ -12,6 +12,7 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
@ -87,12 +88,14 @@ public enum BlockPlacer
if(shape.isEmpty() || state.getMaterial().isReplaceable())
continue;
Vec3d relCenter = shape.getBoundingBox().getCenter();
Vec3d center = Vec3d.of(neighbor).add(relCenter);
Box box = shape.getBoundingBox();
Vec3d halfSize = new Vec3d(box.maxX - box.minX, box.maxY - box.minY,
box.maxZ - box.minZ).multiply(0.5);
Vec3d center = Vec3d.of(neighbor).add(box.getCenter());
Vec3i dirVec = sides[i].getOpposite().getVector();
Vec3d relHitVec = new Vec3d(relCenter.x * dirVec.getX(),
relCenter.y * dirVec.getY(), relCenter.z * dirVec.getZ());
Vec3d relHitVec = new Vec3d(halfSize.x * dirVec.getX(),
halfSize.y * dirVec.getY(), halfSize.z * dirVec.getZ());
hitVecs[i] = center.add(relHitVec);
}

View File

@ -25,6 +25,63 @@ public enum InventoryUtils
private static final MinecraftClient MC = WurstClient.MC;
private static final IMinecraftClient IMC = WurstClient.IMC;
public static int indexOf(Item item)
{
return indexOf(stack -> stack.isOf(item), 36, false);
}
public static int indexOf(Item item, int maxInvSlot)
{
return indexOf(stack -> stack.isOf(item), maxInvSlot, false);
}
public static int indexOf(Item item, int maxInvSlot, boolean includeOffhand)
{
return indexOf(stack -> stack.isOf(item), maxInvSlot, includeOffhand);
}
public static int indexOf(Predicate<ItemStack> predicate)
{
return indexOf(predicate, 36, false);
}
public static int indexOf(Predicate<ItemStack> predicate, int maxInvSlot)
{
return indexOf(predicate, maxInvSlot, false);
}
/**
* Searches the player's inventory from slot 0 to {@code maxInvSlot-1} for
* the first item that matches the given predicate and returns its slot, or
* -1 if no such item was found.
*
* @param predicate
* checks if an item is the one you want
* @param maxInvSlot
* the maximum slot to search (exclusive), usually 9 for the
* hotbar or 36 for the whole inventory
* @param includeOffhand
* also search the offhand (slot 40), even if maxInvSlot is lower
* @return
* the slot of the item, or -1 if no such item was found
*/
public static int indexOf(Predicate<ItemStack> predicate, int maxInvSlot,
boolean includeOffhand)
{
PlayerInventory inventory = MC.player.getInventory();
// create a stream of all slots that we want to search
IntStream stream = IntStream.range(0, maxInvSlot);
if(includeOffhand)
stream = IntStream.concat(stream, IntStream.of(40));
// find the slot of the item we want
int slot = stream.filter(i -> predicate.test(inventory.getStack(i)))
.findFirst().orElse(-1);
return slot;
}
public static boolean selectItem(Item item)
{
return selectItem(stack -> stack.isOf(item), 36, false);
@ -78,18 +135,7 @@ public enum InventoryUtils
public static boolean selectItem(Predicate<ItemStack> predicate,
int maxInvSlot, boolean takeFromOffhand)
{
PlayerInventory inventory = MC.player.getInventory();
// create a stream of all slots that we want to search
IntStream stream = IntStream.range(0, maxInvSlot);
if(takeFromOffhand)
stream = IntStream.concat(stream, IntStream.of(40));
// find the slot of the item we want
int slot = stream.filter(i -> predicate.test(inventory.getStack(i)))
.findFirst().orElse(-1);
return selectItem(slot);
return selectItem(indexOf(predicate, maxInvSlot, takeFromOffhand));
}
/**

View File

@ -74,9 +74,8 @@ public final class OverlayRenderer
pos.getZ() - regionZ);
// get interpolated progress
boolean breaksInstantly = (MC.player.getAbilities().creativeMode
|| BlockUtils.getHardness(pos) >= 1)
&& BlockUtils.canBeClicked(pos);
boolean breaksInstantly = MC.player.getAbilities().creativeMode
|| BlockUtils.getHardness(pos) >= 1;
float p = breaksInstantly ? 1
: MathHelper.lerp(partialTicks, prevProgress, progress);