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:
commit
7901d3a212
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user