package monoton.module.impl.player;
import java.util.Comparator;
import java.util.List;
import monoton.control.events.client.Event;
import monoton.control.events.player.EventUpdate;
import monoton.module.TypeList;
import monoton.module.api.Annotation;
import monoton.module.api.Module;
import monoton.module.settings.Setting;
import monoton.module.settings.imp.BooleanOption;
import monoton.module.settings.imp.ModeSetting;
import monoton.module.settings.imp.SliderSetting;
import monoton.module.settings.imp.TextSetting;
import monoton.utils.IMinecraft;
import monoton.utils.other.StopWatch;
import monoton.utils.world.WorldUtils;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
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;
@Annotation(
name = "AutoLes",
type = TypeList.Player,
desc = "Автоматически ломает брёвна в радиусе 4 блоков"
)
public class AutoLes extends Module implements IMinecraft {
private BlockPos targetPos;
private static final double MAX_RANGE = 4.0D;
private static final double MAX_RANGE_SQ = 16.0D;
private final ModeSetting breakMode = new ModeSetting("Режим", "Default", "Default");
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);
BooleanOption swing = new BooleanOption("Махать рукой", true);
BooleanOption autoWood = new BooleanOption("Авто-сдача", true);
BooleanOption autoPay = new BooleanOption("AutoPay", false);
TextSetting namePay = new TextSetting("Ник для перевода", "name").setVisible(() -> autoPay.get());
SliderSetting valuePay = new SliderSetting("Кол-во монет для перевода", 1000, 500, 25000,1000).setVisible(() -> autoPay.get());
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 final StopWatch packetTimer = new StopWatch();
private int packetsSent = 0;
private long lastBreakTime = 0;
public AutoLes() {
addSettings(breakMode, packetsPerSecond, breakRadius, swing, autoPay, autoWood, namePay, valuePay, timer);
}
public boolean onEvent(Event event) {
if (event instanceof EventUpdate) {
this.updateNuker();
this.autoSell();
this.autoPay();
}
return false;
}
public void autoSell() {
if (autoWood.get() && sellTimer.hasPassed(timer.getValue().intValue() * 500)) {
mc.player.sendChatMessage("/sellwood");
sellTimer.reset();
}
}
public void autoPay() {
if (autoPay.get() && payTimer.hasPassed((timer.getValue().intValue() * 500) + 200)) {
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 = WorldUtils.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.hasPassed(3)) {
mc.playerController.spoofInstantDig(targetPos, Direction.UP);
mc.playerController.onPlayerDestroyBlock(targetPos);
if (swing.get()){
mc.player.swingArm(Hand.MAIN_HAND);
}
breakTimer.reset();
lastBreakTime = System.currentTimeMillis();
}
}
}
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);
}
@Override
public void onDisable() {
targetPos = null;
packetsSent = 0;
super.onDisable();
}
}