package ru.levin.modules.movement;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import ru.levin.events.Event;
import ru.levin.events.impl.EventUpdate;
import ru.levin.modules.Function;
import ru.levin.modules.FunctionAnnotation;
import ru.levin.modules.Type;
import ru.levin.modules.setting.Setting;
import ru.levin.modules.setting.SliderSetting;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("All")
@FunctionAnnotation(name = "BoatNoClip", desc = "Позволяет двигаться на лодке сквозь блоки", type = Type.Move)
public class Phase extends Function {
private final SliderSetting boatUpSpeed =
new SliderSetting("Скорость вверх", 0.4f, 0.05f, 5f, 0.05f);
private final SliderSetting boatDownSpeed =
new SliderSetting("Скорость вниз", 0.4f, 0.05f, 5f, 0.05f);
private final SliderSetting boatHorizontalSpeed =
new SliderSetting("Скорость в стороны", 0.6f, 0.05f, 5f, 0.05f);
private final List<Setting> settings = new ArrayList<>();
public Phase() {
addSettings();
}
private void addSettings() {
settings.add(boatUpSpeed);
settings.add(boatDownSpeed);
settings.add(boatHorizontalSpeed);
}
public List<Setting> getSettings() {
return settings;
}
@Override
public void onEvent(Event event) {
if (event instanceof EventUpdate) {
onUpdate((EventUpdate) event);
}
}
private void onUpdate(EventUpdate event) {
if (mc.player == null || mc.world == null) return;
Entity entity = mc.player.getVehicle();
if (!(entity instanceof BoatEntity boat)) return;
// 🚤 NoClip флаги
boat.noClip = true;
boat.setNoGravity(true);
// ❌ Блок выхода
mc.options.sneakKey.setPressed(false);
// 🔍 Проверка: внутри блока?
boolean insideBlock = isInsideSolidBlock();
double horizontalSpeed = insideBlock
? 0.25D
: getSliderValue(boatHorizontalSpeed);
// 🔁 СИНХРОНИЗАЦИЯ ПОВОРОТА
boat.setYaw(mc.player.getYaw());
boat.prevYaw = boat.getYaw();
double motionX = 0;
double motionY = 0;
double motionZ = 0;
float yaw = boat.getYaw();
double rad = Math.toRadians(yaw);
// ⬆ Вверх
if (mc.options.jumpKey.isPressed())
motionY += getSliderValue(boatUpSpeed);
// ⬇ Вниз (BACK)
if (mc.options.backKey.isPressed())
motionY -= getSliderValue(boatDownSpeed);
// ⬆ Вперёд
if (mc.options.forwardKey.isPressed()) {
motionX -= MathHelper.sin((float) rad) * horizontalSpeed;
motionZ += MathHelper.cos((float) rad) * horizontalSpeed;
}
// ⬅ Влево
if (mc.options.leftKey.isPressed()) {
motionX -= MathHelper.cos((float) rad) * horizontalSpeed;
motionZ -= MathHelper.sin((float) rad) * horizontalSpeed;
}
// ➡ Вправо
if (mc.options.rightKey.isPressed()) {
motionX += MathHelper.cos((float) rad) * horizontalSpeed;
motionZ += MathHelper.sin((float) rad) * horizontalSpeed;
}
// Применяем движение
Vec3d velocity = new Vec3d(motionX, motionY, motionZ);
boat.setVelocity(velocity);
// 🔒 Антивыход
if (!mc.player.hasVehicle()) {
mc.player.startRiding(boat, true);
}
}
// Метод для получения значения из SliderSetting
private double getSliderValue(SliderSetting setting) {
// В зависимости от реализации вашего SliderSetting
// Это может быть getValue(), getFloatValue() или просто value
try {
// Попробуем разные варианты
if (setting instanceof SliderSetting) {
// Вариант 1: метод getValue()
try {
java.lang.reflect.Method method = setting.getClass().getMethod("getValue");
Object result = method.invoke(setting);
if (result instanceof Number) {
return ((Number) result).doubleValue();
}
} catch (Exception e) {
// Игнорируем и пробуем следующий вариант
}
// Вариант 2: метод getFloatValue()
try {
java.lang.reflect.Method method = setting.getClass().getMethod("getFloatValue");
Object result = method.invoke(setting);
if (result instanceof Number) {
return ((Number) result).doubleValue();
}
} catch (Exception e) {
// Игнорируем
}
// Вариант 3: прямое поле value
try {
java.lang.reflect.Field field = setting.getClass().getDeclaredField("value");
field.setAccessible(true);
Object value = field.get(setting);
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
} catch (Exception e) {
// Игнорируем
}
}
} catch (Exception e) {
e.printStackTrace();
}
// Значение по умолчанию
return 0.5;
}
// Альтернативный упрощенный метод, если знаете структуру SliderSetting
private double getValueSimple(SliderSetting setting) {
// Если в вашем SliderSetting есть публичное поле value
return setting.value;
}
private boolean isInsideSolidBlock() {
if (mc.player == null) return false;
Box box = mc.player.getBoundingBox().expand(0.001D);
int minX = MathHelper.floor(box.minX);
int minY = MathHelper.floor(box.minY);
int minZ = MathHelper.floor(box.minZ);
int maxX = MathHelper.floor(box.maxX);
int maxY = MathHelper.floor(box.maxY);
int maxZ = MathHelper.floor(box.maxZ);
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
for (int z = minZ; z <= maxZ; z++) {
BlockPos pos = BlockPos.ofFloored(x, y, z);
BlockState state = mc.world.getBlockState(pos);
if (state.isSolid()) {
return true;
}
}
}
}
return false;
}
@Override
public void onDisable() {
super.onDisable();
if (mc.player != null && mc.player.getVehicle() instanceof BoatEntity boat) {
boat.noClip = false;
boat.setNoGravity(false);
}
}
}