package ru.cheat.modules.impl.player;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import com.google.common.eventbus.Subscribe;
import net.minecraft.block.BlockState;
import net.minecraft.network.play.client.CPlayerDiggingPacket;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import ru.cheat.events.EventUpdate;
import ru.cheat.modules.api.Category;
import ru.cheat.modules.api.ModuleRegister;
import ru.cheat.modules.api.Module;
import ru.cheat.modules.settings.impl.*;
import ru.cheat.utils.math.StopWatch;
@ModuleRegister(name = "AutoLes", category = Category.Player, description = "Быстро ломает деревья на RW")
public class AutoLes extends Module {
private BlockPos targetPos;
private static final double MAX_RANGE_SQ = 16.0D;
private final ModeSetting breakMode = new ModeSetting("Режим", "Default", "Default", "Fast");
private final SliderSetting packetsPerSecond = new SliderSetting("Пакетов/сек", 20.0f, 1.0f, 100.0f, 1.0f)
.setVisible(() -> breakMode.is("Fast"));
private final SliderSetting breakRadius = new SliderSetting("Радиус", 4.0f, 1.0f, 6.0f, 0.5f);
private final BooleanSetting swing = new BooleanSetting("Махать рукой", true);
private final BooleanSetting autoWood = new BooleanSetting("Авто-сдача", true);
private final BooleanSetting autoPay = new BooleanSetting("AutoPay", false);
private final StringSetting namePay = new StringSetting("Ник для перевода", "name", "Ник для перевода").setVisible(() -> autoPay.get());
private final SliderSetting valuePay = new SliderSetting("Кол-во монет для перевода", 1000, 500, 25000,1000).setVisible(() -> autoPay.get());
private final SliderSetting timer = new SliderSetting("Расписание/c", 20, 1, 60, 1).setVisible(() -> autoPay.get());
private final StopWatch sellTimer = new StopWatch();
private final StopWatch payTimer = new StopWatch();
private final StopWatch breakTimer = new StopWatch();
private int packetsSent = 0;
private long lastBreakTime = 0;
public AutoLes() {
addSettings(breakMode, packetsPerSecond, breakRadius, swing, autoPay, autoWood, namePay, valuePay, timer);
}
@Subscribe
public void onUpdate(EventUpdate e) {
this.updateNuker();
this.autoSell();
this.autoPay();
}
public void autoSell() {
if (autoWood.get() && sellTimer.hasTimeElapsed(timer.getValue().intValue() * 500L, false)) {
mc.player.sendChatMessage("/sellwood");
sellTimer.reset();
}
}
public void autoPay() {
if (autoPay.get() && payTimer.hasTimeElapsed((timer.getValue().intValue() * 500) + 200, false)) {
mc.player.sendChatMessage("/pay " + namePay.get() + " " + valuePay.getValue().intValue());
payTimer.reset();
}
}
private void updateNuker() {
if (mc.player == null || mc.world == null) {
targetPos = null;
packetsSent = 0;
return;
}
if (targetPos != null &&
(!isLog(targetPos) || !isInRange(targetPos) || !isVisible(targetPos))) {
targetPos = null;
}
if (targetPos != null) {
breakBlock();
} else {
findAndBreakNewTarget();
}
}
private void findAndBreakNewTarget() {
BlockPos playerPos = mc.player.getPosition();
int radius = (int) breakRadius.getValue().floatValue();
BlockPos from = playerPos.add(-radius, -radius, -radius);
BlockPos to = playerPos.add(radius, radius, radius);
List<BlockPos> blocks = getAllInBox(from, to);
targetPos = blocks.stream()
.filter(this::isLog)
.filter(this::isInRange)
.filter(this::isVisible)
.min(Comparator.comparing(pos ->
mc.player.getDistanceSq(Vector3d.copyCentered(pos))
))
.orElse(null);
if (targetPos != null) {
breakBlock();
}
}
private void breakBlock() {
if (targetPos == null) return;
if (breakMode.is("Default")) {
if (breakTimer.hasTimeElapsed(3, false)) {
mc.playerController.spoofInstantDig(targetPos, Direction.UP);
mc.playerController.onPlayerDestroyBlock(targetPos);
if (swing.get()){
mc.player.swingArm(Hand.MAIN_HAND);
}
breakTimer.reset();
lastBreakTime = System.currentTimeMillis();
}
} else if (breakMode.is("Fast")) {
performFastBreak(targetPos);
}
}
private void performFastBreak(BlockPos pos) {
if (mc.player == null || mc.world == null || mc.getConnection() == null) return;
mc.getConnection().sendPacket(new CPlayerDiggingPacket(
CPlayerDiggingPacket.Action.START_DESTROY_BLOCK,
pos,
Direction.UP
));
mc.getConnection().sendPacket(new CPlayerDiggingPacket(
CPlayerDiggingPacket.Action.STOP_DESTROY_BLOCK,
pos,
Direction.UP
));
mc.player.swingArm(Hand.MAIN_HAND);
}
private boolean isInRange(BlockPos pos) {
if (mc.player == null) return false;
double distanceSq = mc.player.getDistanceSq(
pos.getX() + 0.5,
pos.getY() + 0.5,
pos.getZ() + 0.5
);
return distanceSq <= MAX_RANGE_SQ;
}
private boolean isVisible(BlockPos pos) {
if (mc.world == null || mc.player == null) return false;
return true;
}
private boolean isLog(BlockPos pos) {
if (mc.world == null) return false;
BlockState state = mc.world.getBlockState(pos);
return state.isIn(BlockTags.LOGS);
}
public static List<BlockPos> getAllInBox(BlockPos from, BlockPos to) {
List<BlockPos> blocks = new ArrayList<>();
int minX = Math.min(from.getX(), to.getX());
int minY = Math.min(from.getY(), to.getY());
int minZ = Math.min(from.getZ(), to.getZ());
int maxX = Math.max(from.getX(), to.getX());
int maxY = Math.max(from.getY(), to.getY());
int maxZ = Math.max(from.getZ(), to.getZ());
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
for (int z = minZ; z <= maxZ; z++) {
blocks.add(new BlockPos(x, y, z));
}
}
}
return blocks;
}
@Override
public boolean onDisable() {
targetPos = null;
packetsSent = 0;
super.onDisable();
return false;
}
}