Визуальная часть GPS + AutoGPS | Zenith Recode 1.21.4

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
24 Фев 2023
Сообщения
6
Реакции
0
Выберите загрузчик игры
  1. Fabric
Решил сделать, так-же полу вайб код, старался, но для пастерков нямка нямка, буду рад отзывам, делаю стараюсь :(
старался если что не бейте, имеет баг визуальный что две метки одна вертикальная другой, но если что 3д метку выключить можно, хз как фиксить, кто шарит подскажите пожалуйста

ss:
Пожалуйста, авторизуйтесь для просмотра ссылки.


.gps test можете

GPS.java:
Expand Collapse Copy
package zenith.zov.client.modules.impl.render;

import com.darkmagician6.eventapi.EventTarget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zenith.zov.Zenith;
import zenith.zov.base.events.impl.server.EventPacket;
import zenith.zov.base.events.impl.render.EventHudRender;
import zenith.zov.client.hud.elements.component.EventFTComponent;
import zenith.zov.base.font.Font;
import zenith.zov.base.font.Fonts;
import zenith.zov.base.theme.Theme;
import zenith.zov.client.modules.api.Category;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.api.ModuleAnnotation;
import zenith.zov.client.modules.api.setting.impl.BooleanSetting;
import zenith.zov.client.modules.api.setting.impl.ModeSetting;
import zenith.zov.client.modules.api.setting.impl.NumberSetting;
import zenith.zov.utility.render.display.base.CustomDrawContext;
import zenith.zov.utility.render.display.base.BorderRadius;
import zenith.zov.utility.render.display.shader.DrawUtil;
import zenith.zov.utility.math.ProjectionUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@ModuleAnnotation(name = "GPS", description = "Показывает стрелку к заданным координатам", category = Category.RENDER)
public class GPS extends Module {
    public static final GPS INSTANCE = new GPS();

    private GPS() {
    }

    private final NumberSetting distanceFromCenter = new NumberSetting("Дистанция от центра", 50, 30, 150, 5);
    private final NumberSetting arrowSize = new NumberSetting("Размер стрелки", 32, 16, 64, 2);
    private final NumberSetting markerSize = new NumberSetting("Размер метки 3D", 1.5f, 0.5f, 3f, 0.1f);
    private final BooleanSetting showDistance = new BooleanSetting("Показывать дистанцию", true);
    private final BooleanSetting show3DMarker = new BooleanSetting("Показывать 3D метку", true);
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting arrowColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет стрелки HUD", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting markerIconColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет иконки метки", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 100, 100, 255));

    private final BooleanSetting autoGPS = new BooleanSetting("АвтоGPS", false);
    private final ModeSetting autoGPSMode = new ModeSetting("Режим", autoGPS::isEnabled);
    private final ModeSetting.Value funtime = new ModeSetting.Value(autoGPSMode, "Funtime").select();

    private final Identifier arrowTexture = Zenith.id("icons/gps_arrow.png");

    private static double targetX = 0;
    private static double targetY = 0;
    private static double targetZ = 0;
    private static boolean hasTarget = false;
    private static String lastEventName = "";

    private float smoothAngle = 0;
    private double smoothArrowX = 0;
    private double smoothArrowY = 0;

    private static final Pattern METEOR_PATTERN = Pattern
            .compile("Метеоритный дождь.*?\\[(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)\\]");
    private static final Pattern VOLCANO_PATTERN = Pattern
            .compile("Вулкан.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern KILLER_BEACON_PATTERN = Pattern
            .compile("Маяк убийца.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern DEATH_CHEST_PATTERN = Pattern
            .compile("Сундук Смерти.*?Появится уже через (\\d+) минут");
    private static final Pattern EVENT_STARTED_PATTERN = Pattern
            .compile("(Портал на резню активирован|Идёт страшный бой)");

    public static void setTarget(double x, double y, double z) {
        setTarget(x, y, z, "");
    }

    public static void setTarget(double x, double y, double z, String eventName) {
        targetX = x;
        targetY = y;
        targetZ = z;
        hasTarget = true;
        lastEventName = eventName;
    }

    public static void clearTarget() {
        hasTarget = false;
        lastEventName = "";
    }

    public static boolean hasTarget() {
        return hasTarget;
    }

    public static String getLastEventName() {
        return lastEventName;
    }

    public static double getTargetX() {
        return targetX;
    }

    public static double getTargetY() {
        return targetY;
    }

    public static double getTargetZ() {
        return targetZ;
    }

    @EventTarget
    public void onHudRender(EventHudRender event) {
        if (mc.player == null || mc.world == null || !hasTarget)
            return;

        CustomDrawContext ctx = event.getContext();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();
        Font font = Fonts.MEDIUM.getFont(5);

        float centerX = ctx.getScaledWindowWidth() / 2f;
        float centerY = ctx.getScaledWindowHeight() / 2f;

        double playerX = mc.player.getX();
        double playerZ = mc.player.getZ();

        double deltaX = targetX - playerX;
        double deltaZ = targetZ - playerZ;

        double distance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);

        float yaw = mc.player.getYaw();
        double yawRad = Math.toRadians(yaw);

        double cos = Math.cos(yawRad);
        double sin = Math.sin(yawRad);

        double rotY = -(deltaZ * cos - deltaX * sin);
        double rotX = -(deltaX * cos + deltaZ * sin);

        if (Math.abs(rotX) < 0.01 && Math.abs(rotY) < 0.01)
            return;

        float targetAngle = (float) (Math.atan2(rotY, rotX) * 180 / Math.PI);

        // Плавная интерполяция угла
        float angleDiff = targetAngle - smoothAngle;
        while (angleDiff > 180)
            angleDiff -= 360;
        while (angleDiff < -180)
            angleDiff += 360;
        smoothAngle += angleDiff * 0.3f;

        double targetArrowX = distanceFromCenter.getCurrent() * MathHelper.cos((float) Math.toRadians(targetAngle))
                + centerX;
        double targetArrowY = distanceFromCenter.getCurrent() * MathHelper.sin((float) Math.toRadians(targetAngle))
                + centerY;

        // Плавная интерполяция позиции
        smoothArrowX += (targetArrowX - smoothArrowX) * 0.3;
        smoothArrowY += (targetArrowY - smoothArrowY) * 0.3;

        float size = arrowSize.getCurrent();

        ctx.pushMatrix();
        ctx.getMatrices().translate(smoothArrowX, smoothArrowY, 0);
        ctx.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(smoothAngle + 90));
        ctx.getMatrices().translate(-size / 2, -size / 2, 0);

        zenith.zov.utility.render.display.base.color.ColorRGBA arrowColor = getArrowColor();
        ctx.drawTexture(arrowTexture, 0, 0, size, size, arrowColor);

        ctx.popMatrix();

        if (showDistance.isEnabled()) {
            String distanceText = String.format("%.0f", distance);
            float textWidth = font.width(distanceText);

            float textAngleRad = (float) Math.toRadians(smoothAngle);
            float textX = (float) smoothArrowX + MathHelper.cos(textAngleRad) * (size / 2 + 5);
            float textY = (float) smoothArrowY + MathHelper.sin(textAngleRad) * (size / 2 + 5);

            ctx.drawText(font, distanceText, textX - textWidth / 2, textY - font.height() / 2, getArrowColor());
        }
    }

    private zenith.zov.utility.render.display.base.color.ColorRGBA getArrowColor() {
        return arrowColor.getColor();
    }

    public static void processMessage(String message) {
        if (!INSTANCE.autoGPS.isEnabled() || mc.player == null) return;
        
        // Убираем все цветовые коды, форматирование и невидимые символы
        String cleanMessage = message
                .replaceAll("§[0-9a-fk-or]", "") // Minecraft цвета
                .replaceAll("&[0-9a-fk-or]", "") // Альтернативные цвета
                .replaceAll("[\\x00-\\x1F\\x7F]", "") // Управляющие символы
                .replaceAll("\\p{C}", ""); // Все невидимые Unicode символы

        if (INSTANCE.funtime.isSelected()) {
            // Проверяем начало ивента (портал активирован / идёт бой = выключаем GPS)
            Matcher eventStartedMatcher = EVENT_STARTED_PATTERN.matcher(cleanMessage);
            if (eventStartedMatcher.find()) {
                clearTarget();
                if (mc.player != null) {
                    mc.player.sendMessage(
                            Text.literal("§cGPS метка снята - §6Ивент начался!"),
                            true);
                }
                return;
            }
            
            // Проверяем сундук смерти (появится через 3 минуты = выключаем GPS)
            Matcher deathChestMatcher = DEATH_CHEST_PATTERN.matcher(cleanMessage);
            if (deathChestMatcher.find()) {
                try {
                    int minutes = Integer.parseInt(deathChestMatcher.group(1));
                    if (minutes == 3) {
                        clearTarget();
                        if (mc.player != null) {
                            mc.player.sendMessage(
                                    Text.literal("§cGPS метка снята - §6Сундук Смерти §cпоявится через 3 минуты"),
                                    true);
                        }
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }

            // Ищем паттерн метеоритного дождя
            Matcher meteorMatcher = METEOR_PATTERN.matcher(cleanMessage);
            if (meteorMatcher.find()) {
                try {
                    int x = Integer.parseInt(meteorMatcher.group(1));
                    int y = Integer.parseInt(meteorMatcher.group(2));
                    int z = Integer.parseInt(meteorMatcher.group(3));

                    setTarget(x, y, z, "Метеоритный дождь");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Метеоритный дождь"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
            
            // Ищем паттерн вулкана
            Matcher volcanoMatcher = VOLCANO_PATTERN.matcher(cleanMessage);
            if (volcanoMatcher.find()) {
                try {
                    int x = Integer.parseInt(volcanoMatcher.group(1));
                    int y = Integer.parseInt(volcanoMatcher.group(2));
                    int z = Integer.parseInt(volcanoMatcher.group(3));

                    setTarget(x, y, z, "Вулкан");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Вулкан"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
            
            // Ищем паттерн маяка убийцы
            Matcher killerBeaconMatcher = KILLER_BEACON_PATTERN.matcher(cleanMessage);
            if (killerBeaconMatcher.find()) {
                try {
                    int x = Integer.parseInt(killerBeaconMatcher.group(1));
                    int y = Integer.parseInt(killerBeaconMatcher.group(2));
                    int z = Integer.parseInt(killerBeaconMatcher.group(3));

                    setTarget(x, y, z, "Маяк убийца");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Маяк убийца"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
            }
        }
        
        // Обрабатываем сообщения для EventFTComponent
        EventFTComponent.processEventMessage(message);
    }
    
    @EventTarget
    public void onPacket(EventPacket event) {
        if (mc.player == null || !event.isReceive())
            return;

        // Обрабатываем сообщения для автоGPS
        if (autoGPS.isEnabled() && event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameMessageS2CPacket packet) {
            processMessage(packet.content().getString());
        }
        
        // Отслеживаем заход на сервер (GameJoinS2CPacket)
        if (event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameJoinS2CPacket) {
            EventFTComponent.onServerJoin();
        }
    }

    @EventTarget
    public void onRender2D(zenith.zov.base.events.impl.render.EventRender2D event) {
        if (mc.player == null || mc.world == null || !hasTarget || !show3DMarker.isEnabled())
            return;

        double playerX = mc.player.getX();
        double playerY = mc.player.getY();
        double playerZ = mc.player.getZ();

        double distance = Math.sqrt((targetX - playerX) * (targetX - playerX)
                + (targetY - playerY) * (targetY - playerY) + (targetZ - playerZ) * (targetZ - playerZ));

        // Получаем проекцию точки на экран
        Vec3d targetPos = new Vec3d(targetX, targetY, targetZ);
        Vec3d projected = ProjectionUtil.worldSpaceToScreenSpace(targetPos);

        CustomDrawContext context = event.getContext();
        Font font = Fonts.MEDIUM.getFont(8 * markerSize.getCurrent());
        zenith.zov.utility.render.display.base.color.ColorRGBA color = getArrowColor();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();

        float posX = (float) projected.x;
        float posY = (float) projected.y;

        // Размеры иконки
        float iconSize = 16 * markerSize.getCurrent();

        // Текст
        String gpsText = "GPS";
        String distText = String.format("%.0fm", distance);
        float gpsWidth = font.width(gpsText);
        float distWidth = font.width(distText);
        float maxTextWidth = Math.max(gpsWidth, distWidth);

        // Размеры прямоугольника
        float rectWidth = maxTextWidth + 16 * markerSize.getCurrent();
        float rectHeight = (font.height() * 2 + 6) * markerSize.getCurrent();
        float rectX = posX - rectWidth / 2;
        float rectY = posY + iconSize + 4 * markerSize.getCurrent();

        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().scale(markerSize.getCurrent(), markerSize.getCurrent(), 1f);
        context.getMatrices().translate(-posX, -posY, 0);

        // Рисуем фон для текста
        DrawUtil.drawBlurHud(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 22, BorderRadius.all(2),
                new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
        context.drawRoundedRect(rectX, rectY, rectWidth, rectHeight, BorderRadius.all(2), theme.getForegroundLight());
        DrawUtil.drawRoundedCorner(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 0.1f, 9, color,
                BorderRadius.all(2));

        // Рисуем иконку стрелки (перевернутую вниз, чуть ниже)
        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(180));
        context.drawTexture(arrowTexture, -iconSize / 2, -iconSize / 2, iconSize, iconSize, markerIconColor.getColor());
        context.popMatrix();

        // Рисуем текст
        context.drawText(font, gpsText, posX - gpsWidth / 2, rectY + 3 * markerSize.getCurrent(), color);
        context.drawText(font, distText, posX - distWidth / 2, rectY + 3 * markerSize.getCurrent() + font.height() + 2,
                color);

        context.popMatrix();
    }
}
 

Вложения

  • gps_arrow.png
    gps_arrow.png
    7.3 KB · Просмотры: 17
Решил сделать, так-же полу вайб код, старался, но для пастерков нямка нямка, буду рад отзывам, делаю стараюсь :(
старался если что не бейте, имеет баг визуальный что две метки одна вертикальная другой, но если что 3д метку выключить можно, хз как фиксить, кто шарит подскажите пожалуйста

ss:
Пожалуйста, авторизуйтесь для просмотра ссылки.


.gps test можете

GPS.java:
Expand Collapse Copy
package zenith.zov.client.modules.impl.render;

import com.darkmagician6.eventapi.EventTarget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zenith.zov.Zenith;
import zenith.zov.base.events.impl.server.EventPacket;
import zenith.zov.base.events.impl.render.EventHudRender;
import zenith.zov.client.hud.elements.component.EventFTComponent;
import zenith.zov.base.font.Font;
import zenith.zov.base.font.Fonts;
import zenith.zov.base.theme.Theme;
import zenith.zov.client.modules.api.Category;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.api.ModuleAnnotation;
import zenith.zov.client.modules.api.setting.impl.BooleanSetting;
import zenith.zov.client.modules.api.setting.impl.ModeSetting;
import zenith.zov.client.modules.api.setting.impl.NumberSetting;
import zenith.zov.utility.render.display.base.CustomDrawContext;
import zenith.zov.utility.render.display.base.BorderRadius;
import zenith.zov.utility.render.display.shader.DrawUtil;
import zenith.zov.utility.math.ProjectionUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@ModuleAnnotation(name = "GPS", description = "Показывает стрелку к заданным координатам", category = Category.RENDER)
public class GPS extends Module {
    public static final GPS INSTANCE = new GPS();

    private GPS() {
    }

    private final NumberSetting distanceFromCenter = new NumberSetting("Дистанция от центра", 50, 30, 150, 5);
    private final NumberSetting arrowSize = new NumberSetting("Размер стрелки", 32, 16, 64, 2);
    private final NumberSetting markerSize = new NumberSetting("Размер метки 3D", 1.5f, 0.5f, 3f, 0.1f);
    private final BooleanSetting showDistance = new BooleanSetting("Показывать дистанцию", true);
    private final BooleanSetting show3DMarker = new BooleanSetting("Показывать 3D метку", true);
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting arrowColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет стрелки HUD", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting markerIconColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет иконки метки", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 100, 100, 255));

    private final BooleanSetting autoGPS = new BooleanSetting("АвтоGPS", false);
    private final ModeSetting autoGPSMode = new ModeSetting("Режим", autoGPS::isEnabled);
    private final ModeSetting.Value funtime = new ModeSetting.Value(autoGPSMode, "Funtime").select();

    private final Identifier arrowTexture = Zenith.id("icons/gps_arrow.png");

    private static double targetX = 0;
    private static double targetY = 0;
    private static double targetZ = 0;
    private static boolean hasTarget = false;
    private static String lastEventName = "";

    private float smoothAngle = 0;
    private double smoothArrowX = 0;
    private double smoothArrowY = 0;

    private static final Pattern METEOR_PATTERN = Pattern
            .compile("Метеоритный дождь.*?\\[(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)\\]");
    private static final Pattern VOLCANO_PATTERN = Pattern
            .compile("Вулкан.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern KILLER_BEACON_PATTERN = Pattern
            .compile("Маяк убийца.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern DEATH_CHEST_PATTERN = Pattern
            .compile("Сундук Смерти.*?Появится уже через (\\d+) минут");
    private static final Pattern EVENT_STARTED_PATTERN = Pattern
            .compile("(Портал на резню активирован|Идёт страшный бой)");

    public static void setTarget(double x, double y, double z) {
        setTarget(x, y, z, "");
    }

    public static void setTarget(double x, double y, double z, String eventName) {
        targetX = x;
        targetY = y;
        targetZ = z;
        hasTarget = true;
        lastEventName = eventName;
    }

    public static void clearTarget() {
        hasTarget = false;
        lastEventName = "";
    }

    public static boolean hasTarget() {
        return hasTarget;
    }

    public static String getLastEventName() {
        return lastEventName;
    }

    public static double getTargetX() {
        return targetX;
    }

    public static double getTargetY() {
        return targetY;
    }

    public static double getTargetZ() {
        return targetZ;
    }

    @EventTarget
    public void onHudRender(EventHudRender event) {
        if (mc.player == null || mc.world == null || !hasTarget)
            return;

        CustomDrawContext ctx = event.getContext();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();
        Font font = Fonts.MEDIUM.getFont(5);

        float centerX = ctx.getScaledWindowWidth() / 2f;
        float centerY = ctx.getScaledWindowHeight() / 2f;

        double playerX = mc.player.getX();
        double playerZ = mc.player.getZ();

        double deltaX = targetX - playerX;
        double deltaZ = targetZ - playerZ;

        double distance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);

        float yaw = mc.player.getYaw();
        double yawRad = Math.toRadians(yaw);

        double cos = Math.cos(yawRad);
        double sin = Math.sin(yawRad);

        double rotY = -(deltaZ * cos - deltaX * sin);
        double rotX = -(deltaX * cos + deltaZ * sin);

        if (Math.abs(rotX) < 0.01 && Math.abs(rotY) < 0.01)
            return;

        float targetAngle = (float) (Math.atan2(rotY, rotX) * 180 / Math.PI);

        // Плавная интерполяция угла
        float angleDiff = targetAngle - smoothAngle;
        while (angleDiff > 180)
            angleDiff -= 360;
        while (angleDiff < -180)
            angleDiff += 360;
        smoothAngle += angleDiff * 0.3f;

        double targetArrowX = distanceFromCenter.getCurrent() * MathHelper.cos((float) Math.toRadians(targetAngle))
                + centerX;
        double targetArrowY = distanceFromCenter.getCurrent() * MathHelper.sin((float) Math.toRadians(targetAngle))
                + centerY;

        // Плавная интерполяция позиции
        smoothArrowX += (targetArrowX - smoothArrowX) * 0.3;
        smoothArrowY += (targetArrowY - smoothArrowY) * 0.3;

        float size = arrowSize.getCurrent();

        ctx.pushMatrix();
        ctx.getMatrices().translate(smoothArrowX, smoothArrowY, 0);
        ctx.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(smoothAngle + 90));
        ctx.getMatrices().translate(-size / 2, -size / 2, 0);

        zenith.zov.utility.render.display.base.color.ColorRGBA arrowColor = getArrowColor();
        ctx.drawTexture(arrowTexture, 0, 0, size, size, arrowColor);

        ctx.popMatrix();

        if (showDistance.isEnabled()) {
            String distanceText = String.format("%.0f", distance);
            float textWidth = font.width(distanceText);

            float textAngleRad = (float) Math.toRadians(smoothAngle);
            float textX = (float) smoothArrowX + MathHelper.cos(textAngleRad) * (size / 2 + 5);
            float textY = (float) smoothArrowY + MathHelper.sin(textAngleRad) * (size / 2 + 5);

            ctx.drawText(font, distanceText, textX - textWidth / 2, textY - font.height() / 2, getArrowColor());
        }
    }

    private zenith.zov.utility.render.display.base.color.ColorRGBA getArrowColor() {
        return arrowColor.getColor();
    }

    public static void processMessage(String message) {
        if (!INSTANCE.autoGPS.isEnabled() || mc.player == null) return;
       
        // Убираем все цветовые коды, форматирование и невидимые символы
        String cleanMessage = message
                .replaceAll("§[0-9a-fk-or]", "") // Minecraft цвета
                .replaceAll("&[0-9a-fk-or]", "") // Альтернативные цвета
                .replaceAll("[\\x00-\\x1F\\x7F]", "") // Управляющие символы
                .replaceAll("\\p{C}", ""); // Все невидимые Unicode символы

        if (INSTANCE.funtime.isSelected()) {
            // Проверяем начало ивента (портал активирован / идёт бой = выключаем GPS)
            Matcher eventStartedMatcher = EVENT_STARTED_PATTERN.matcher(cleanMessage);
            if (eventStartedMatcher.find()) {
                clearTarget();
                if (mc.player != null) {
                    mc.player.sendMessage(
                            Text.literal("§cGPS метка снята - §6Ивент начался!"),
                            true);
                }
                return;
            }
           
            // Проверяем сундук смерти (появится через 3 минуты = выключаем GPS)
            Matcher deathChestMatcher = DEATH_CHEST_PATTERN.matcher(cleanMessage);
            if (deathChestMatcher.find()) {
                try {
                    int minutes = Integer.parseInt(deathChestMatcher.group(1));
                    if (minutes == 3) {
                        clearTarget();
                        if (mc.player != null) {
                            mc.player.sendMessage(
                                    Text.literal("§cGPS метка снята - §6Сундук Смерти §cпоявится через 3 минуты"),
                                    true);
                        }
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }

            // Ищем паттерн метеоритного дождя
            Matcher meteorMatcher = METEOR_PATTERN.matcher(cleanMessage);
            if (meteorMatcher.find()) {
                try {
                    int x = Integer.parseInt(meteorMatcher.group(1));
                    int y = Integer.parseInt(meteorMatcher.group(2));
                    int z = Integer.parseInt(meteorMatcher.group(3));

                    setTarget(x, y, z, "Метеоритный дождь");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Метеоритный дождь"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
           
            // Ищем паттерн вулкана
            Matcher volcanoMatcher = VOLCANO_PATTERN.matcher(cleanMessage);
            if (volcanoMatcher.find()) {
                try {
                    int x = Integer.parseInt(volcanoMatcher.group(1));
                    int y = Integer.parseInt(volcanoMatcher.group(2));
                    int z = Integer.parseInt(volcanoMatcher.group(3));

                    setTarget(x, y, z, "Вулкан");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Вулкан"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
           
            // Ищем паттерн маяка убийцы
            Matcher killerBeaconMatcher = KILLER_BEACON_PATTERN.matcher(cleanMessage);
            if (killerBeaconMatcher.find()) {
                try {
                    int x = Integer.parseInt(killerBeaconMatcher.group(1));
                    int y = Integer.parseInt(killerBeaconMatcher.group(2));
                    int z = Integer.parseInt(killerBeaconMatcher.group(3));

                    setTarget(x, y, z, "Маяк убийца");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Маяк убийца"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
            }
        }
       
        // Обрабатываем сообщения для EventFTComponent
        EventFTComponent.processEventMessage(message);
    }
   
    @EventTarget
    public void onPacket(EventPacket event) {
        if (mc.player == null || !event.isReceive())
            return;

        // Обрабатываем сообщения для автоGPS
        if (autoGPS.isEnabled() && event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameMessageS2CPacket packet) {
            processMessage(packet.content().getString());
        }
       
        // Отслеживаем заход на сервер (GameJoinS2CPacket)
        if (event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameJoinS2CPacket) {
            EventFTComponent.onServerJoin();
        }
    }

    @EventTarget
    public void onRender2D(zenith.zov.base.events.impl.render.EventRender2D event) {
        if (mc.player == null || mc.world == null || !hasTarget || !show3DMarker.isEnabled())
            return;

        double playerX = mc.player.getX();
        double playerY = mc.player.getY();
        double playerZ = mc.player.getZ();

        double distance = Math.sqrt((targetX - playerX) * (targetX - playerX)
                + (targetY - playerY) * (targetY - playerY) + (targetZ - playerZ) * (targetZ - playerZ));

        // Получаем проекцию точки на экран
        Vec3d targetPos = new Vec3d(targetX, targetY, targetZ);
        Vec3d projected = ProjectionUtil.worldSpaceToScreenSpace(targetPos);

        CustomDrawContext context = event.getContext();
        Font font = Fonts.MEDIUM.getFont(8 * markerSize.getCurrent());
        zenith.zov.utility.render.display.base.color.ColorRGBA color = getArrowColor();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();

        float posX = (float) projected.x;
        float posY = (float) projected.y;

        // Размеры иконки
        float iconSize = 16 * markerSize.getCurrent();

        // Текст
        String gpsText = "GPS";
        String distText = String.format("%.0fm", distance);
        float gpsWidth = font.width(gpsText);
        float distWidth = font.width(distText);
        float maxTextWidth = Math.max(gpsWidth, distWidth);

        // Размеры прямоугольника
        float rectWidth = maxTextWidth + 16 * markerSize.getCurrent();
        float rectHeight = (font.height() * 2 + 6) * markerSize.getCurrent();
        float rectX = posX - rectWidth / 2;
        float rectY = posY + iconSize + 4 * markerSize.getCurrent();

        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().scale(markerSize.getCurrent(), markerSize.getCurrent(), 1f);
        context.getMatrices().translate(-posX, -posY, 0);

        // Рисуем фон для текста
        DrawUtil.drawBlurHud(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 22, BorderRadius.all(2),
                new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
        context.drawRoundedRect(rectX, rectY, rectWidth, rectHeight, BorderRadius.all(2), theme.getForegroundLight());
        DrawUtil.drawRoundedCorner(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 0.1f, 9, color,
                BorderRadius.all(2));

        // Рисуем иконку стрелки (перевернутую вниз, чуть ниже)
        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(180));
        context.drawTexture(arrowTexture, -iconSize / 2, -iconSize / 2, iconSize, iconSize, markerIconColor.getColor());
        context.popMatrix();

        // Рисуем текст
        context.drawText(font, gpsText, posX - gpsWidth / 2, rectY + 3 * markerSize.getCurrent(), color);
        context.drawText(font, distText, posX - distWidth / 2, rectY + 3 * markerSize.getCurrent() + font.height() + 2,
                color);

        context.popMatrix();
    }
}
А что он делает?
Решил сделать, так-же полу вайб код, старался, но для пастерков нямка нямка, буду рад отзывам, делаю стараюсь :(
старался если что не бейте, имеет баг визуальный что две метки одна вертикальная другой, но если что 3д метку выключить можно, хз как фиксить, кто шарит подскажите пожалуйста

ss:
Пожалуйста, авторизуйтесь для просмотра ссылки.


.gps test можете

GPS.java:
Expand Collapse Copy
package zenith.zov.client.modules.impl.render;

import com.darkmagician6.eventapi.EventTarget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zenith.zov.Zenith;
import zenith.zov.base.events.impl.server.EventPacket;
import zenith.zov.base.events.impl.render.EventHudRender;
import zenith.zov.client.hud.elements.component.EventFTComponent;
import zenith.zov.base.font.Font;
import zenith.zov.base.font.Fonts;
import zenith.zov.base.theme.Theme;
import zenith.zov.client.modules.api.Category;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.api.ModuleAnnotation;
import zenith.zov.client.modules.api.setting.impl.BooleanSetting;
import zenith.zov.client.modules.api.setting.impl.ModeSetting;
import zenith.zov.client.modules.api.setting.impl.NumberSetting;
import zenith.zov.utility.render.display.base.CustomDrawContext;
import zenith.zov.utility.render.display.base.BorderRadius;
import zenith.zov.utility.render.display.shader.DrawUtil;
import zenith.zov.utility.math.ProjectionUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@ModuleAnnotation(name = "GPS", description = "Показывает стрелку к заданным координатам", category = Category.RENDER)
public class GPS extends Module {
    public static final GPS INSTANCE = new GPS();

    private GPS() {
    }

    private final NumberSetting distanceFromCenter = new NumberSetting("Дистанция от центра", 50, 30, 150, 5);
    private final NumberSetting arrowSize = new NumberSetting("Размер стрелки", 32, 16, 64, 2);
    private final NumberSetting markerSize = new NumberSetting("Размер метки 3D", 1.5f, 0.5f, 3f, 0.1f);
    private final BooleanSetting showDistance = new BooleanSetting("Показывать дистанцию", true);
    private final BooleanSetting show3DMarker = new BooleanSetting("Показывать 3D метку", true);
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting arrowColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет стрелки HUD", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting markerIconColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет иконки метки", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 100, 100, 255));

    private final BooleanSetting autoGPS = new BooleanSetting("АвтоGPS", false);
    private final ModeSetting autoGPSMode = new ModeSetting("Режим", autoGPS::isEnabled);
    private final ModeSetting.Value funtime = new ModeSetting.Value(autoGPSMode, "Funtime").select();

    private final Identifier arrowTexture = Zenith.id("icons/gps_arrow.png");

    private static double targetX = 0;
    private static double targetY = 0;
    private static double targetZ = 0;
    private static boolean hasTarget = false;
    private static String lastEventName = "";

    private float smoothAngle = 0;
    private double smoothArrowX = 0;
    private double smoothArrowY = 0;

    private static final Pattern METEOR_PATTERN = Pattern
            .compile("Метеоритный дождь.*?\\[(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)\\]");
    private static final Pattern VOLCANO_PATTERN = Pattern
            .compile("Вулкан.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern KILLER_BEACON_PATTERN = Pattern
            .compile("Маяк убийца.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern DEATH_CHEST_PATTERN = Pattern
            .compile("Сундук Смерти.*?Появится уже через (\\d+) минут");
    private static final Pattern EVENT_STARTED_PATTERN = Pattern
            .compile("(Портал на резню активирован|Идёт страшный бой)");

    public static void setTarget(double x, double y, double z) {
        setTarget(x, y, z, "");
    }

    public static void setTarget(double x, double y, double z, String eventName) {
        targetX = x;
        targetY = y;
        targetZ = z;
        hasTarget = true;
        lastEventName = eventName;
    }

    public static void clearTarget() {
        hasTarget = false;
        lastEventName = "";
    }

    public static boolean hasTarget() {
        return hasTarget;
    }

    public static String getLastEventName() {
        return lastEventName;
    }

    public static double getTargetX() {
        return targetX;
    }

    public static double getTargetY() {
        return targetY;
    }

    public static double getTargetZ() {
        return targetZ;
    }

    @EventTarget
    public void onHudRender(EventHudRender event) {
        if (mc.player == null || mc.world == null || !hasTarget)
            return;

        CustomDrawContext ctx = event.getContext();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();
        Font font = Fonts.MEDIUM.getFont(5);

        float centerX = ctx.getScaledWindowWidth() / 2f;
        float centerY = ctx.getScaledWindowHeight() / 2f;

        double playerX = mc.player.getX();
        double playerZ = mc.player.getZ();

        double deltaX = targetX - playerX;
        double deltaZ = targetZ - playerZ;

        double distance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);

        float yaw = mc.player.getYaw();
        double yawRad = Math.toRadians(yaw);

        double cos = Math.cos(yawRad);
        double sin = Math.sin(yawRad);

        double rotY = -(deltaZ * cos - deltaX * sin);
        double rotX = -(deltaX * cos + deltaZ * sin);

        if (Math.abs(rotX) < 0.01 && Math.abs(rotY) < 0.01)
            return;

        float targetAngle = (float) (Math.atan2(rotY, rotX) * 180 / Math.PI);

        // Плавная интерполяция угла
        float angleDiff = targetAngle - smoothAngle;
        while (angleDiff > 180)
            angleDiff -= 360;
        while (angleDiff < -180)
            angleDiff += 360;
        smoothAngle += angleDiff * 0.3f;

        double targetArrowX = distanceFromCenter.getCurrent() * MathHelper.cos((float) Math.toRadians(targetAngle))
                + centerX;
        double targetArrowY = distanceFromCenter.getCurrent() * MathHelper.sin((float) Math.toRadians(targetAngle))
                + centerY;

        // Плавная интерполяция позиции
        smoothArrowX += (targetArrowX - smoothArrowX) * 0.3;
        smoothArrowY += (targetArrowY - smoothArrowY) * 0.3;

        float size = arrowSize.getCurrent();

        ctx.pushMatrix();
        ctx.getMatrices().translate(smoothArrowX, smoothArrowY, 0);
        ctx.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(smoothAngle + 90));
        ctx.getMatrices().translate(-size / 2, -size / 2, 0);

        zenith.zov.utility.render.display.base.color.ColorRGBA arrowColor = getArrowColor();
        ctx.drawTexture(arrowTexture, 0, 0, size, size, arrowColor);

        ctx.popMatrix();

        if (showDistance.isEnabled()) {
            String distanceText = String.format("%.0f", distance);
            float textWidth = font.width(distanceText);

            float textAngleRad = (float) Math.toRadians(smoothAngle);
            float textX = (float) smoothArrowX + MathHelper.cos(textAngleRad) * (size / 2 + 5);
            float textY = (float) smoothArrowY + MathHelper.sin(textAngleRad) * (size / 2 + 5);

            ctx.drawText(font, distanceText, textX - textWidth / 2, textY - font.height() / 2, getArrowColor());
        }
    }

    private zenith.zov.utility.render.display.base.color.ColorRGBA getArrowColor() {
        return arrowColor.getColor();
    }

    public static void processMessage(String message) {
        if (!INSTANCE.autoGPS.isEnabled() || mc.player == null) return;
       
        // Убираем все цветовые коды, форматирование и невидимые символы
        String cleanMessage = message
                .replaceAll("§[0-9a-fk-or]", "") // Minecraft цвета
                .replaceAll("&[0-9a-fk-or]", "") // Альтернативные цвета
                .replaceAll("[\\x00-\\x1F\\x7F]", "") // Управляющие символы
                .replaceAll("\\p{C}", ""); // Все невидимые Unicode символы

        if (INSTANCE.funtime.isSelected()) {
            // Проверяем начало ивента (портал активирован / идёт бой = выключаем GPS)
            Matcher eventStartedMatcher = EVENT_STARTED_PATTERN.matcher(cleanMessage);
            if (eventStartedMatcher.find()) {
                clearTarget();
                if (mc.player != null) {
                    mc.player.sendMessage(
                            Text.literal("§cGPS метка снята - §6Ивент начался!"),
                            true);
                }
                return;
            }
           
            // Проверяем сундук смерти (появится через 3 минуты = выключаем GPS)
            Matcher deathChestMatcher = DEATH_CHEST_PATTERN.matcher(cleanMessage);
            if (deathChestMatcher.find()) {
                try {
                    int minutes = Integer.parseInt(deathChestMatcher.group(1));
                    if (minutes == 3) {
                        clearTarget();
                        if (mc.player != null) {
                            mc.player.sendMessage(
                                    Text.literal("§cGPS метка снята - §6Сундук Смерти §cпоявится через 3 минуты"),
                                    true);
                        }
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }

            // Ищем паттерн метеоритного дождя
            Matcher meteorMatcher = METEOR_PATTERN.matcher(cleanMessage);
            if (meteorMatcher.find()) {
                try {
                    int x = Integer.parseInt(meteorMatcher.group(1));
                    int y = Integer.parseInt(meteorMatcher.group(2));
                    int z = Integer.parseInt(meteorMatcher.group(3));

                    setTarget(x, y, z, "Метеоритный дождь");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Метеоритный дождь"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
           
            // Ищем паттерн вулкана
            Matcher volcanoMatcher = VOLCANO_PATTERN.matcher(cleanMessage);
            if (volcanoMatcher.find()) {
                try {
                    int x = Integer.parseInt(volcanoMatcher.group(1));
                    int y = Integer.parseInt(volcanoMatcher.group(2));
                    int z = Integer.parseInt(volcanoMatcher.group(3));

                    setTarget(x, y, z, "Вулкан");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Вулкан"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
           
            // Ищем паттерн маяка убийцы
            Matcher killerBeaconMatcher = KILLER_BEACON_PATTERN.matcher(cleanMessage);
            if (killerBeaconMatcher.find()) {
                try {
                    int x = Integer.parseInt(killerBeaconMatcher.group(1));
                    int y = Integer.parseInt(killerBeaconMatcher.group(2));
                    int z = Integer.parseInt(killerBeaconMatcher.group(3));

                    setTarget(x, y, z, "Маяк убийца");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Маяк убийца"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
            }
        }
       
        // Обрабатываем сообщения для EventFTComponent
        EventFTComponent.processEventMessage(message);
    }
   
    @EventTarget
    public void onPacket(EventPacket event) {
        if (mc.player == null || !event.isReceive())
            return;

        // Обрабатываем сообщения для автоGPS
        if (autoGPS.isEnabled() && event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameMessageS2CPacket packet) {
            processMessage(packet.content().getString());
        }
       
        // Отслеживаем заход на сервер (GameJoinS2CPacket)
        if (event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameJoinS2CPacket) {
            EventFTComponent.onServerJoin();
        }
    }

    @EventTarget
    public void onRender2D(zenith.zov.base.events.impl.render.EventRender2D event) {
        if (mc.player == null || mc.world == null || !hasTarget || !show3DMarker.isEnabled())
            return;

        double playerX = mc.player.getX();
        double playerY = mc.player.getY();
        double playerZ = mc.player.getZ();

        double distance = Math.sqrt((targetX - playerX) * (targetX - playerX)
                + (targetY - playerY) * (targetY - playerY) + (targetZ - playerZ) * (targetZ - playerZ));

        // Получаем проекцию точки на экран
        Vec3d targetPos = new Vec3d(targetX, targetY, targetZ);
        Vec3d projected = ProjectionUtil.worldSpaceToScreenSpace(targetPos);

        CustomDrawContext context = event.getContext();
        Font font = Fonts.MEDIUM.getFont(8 * markerSize.getCurrent());
        zenith.zov.utility.render.display.base.color.ColorRGBA color = getArrowColor();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();

        float posX = (float) projected.x;
        float posY = (float) projected.y;

        // Размеры иконки
        float iconSize = 16 * markerSize.getCurrent();

        // Текст
        String gpsText = "GPS";
        String distText = String.format("%.0fm", distance);
        float gpsWidth = font.width(gpsText);
        float distWidth = font.width(distText);
        float maxTextWidth = Math.max(gpsWidth, distWidth);

        // Размеры прямоугольника
        float rectWidth = maxTextWidth + 16 * markerSize.getCurrent();
        float rectHeight = (font.height() * 2 + 6) * markerSize.getCurrent();
        float rectX = posX - rectWidth / 2;
        float rectY = posY + iconSize + 4 * markerSize.getCurrent();

        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().scale(markerSize.getCurrent(), markerSize.getCurrent(), 1f);
        context.getMatrices().translate(-posX, -posY, 0);

        // Рисуем фон для текста
        DrawUtil.drawBlurHud(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 22, BorderRadius.all(2),
                new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
        context.drawRoundedRect(rectX, rectY, rectWidth, rectHeight, BorderRadius.all(2), theme.getForegroundLight());
        DrawUtil.drawRoundedCorner(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 0.1f, 9, color,
                BorderRadius.all(2));

        // Рисуем иконку стрелки (перевернутую вниз, чуть ниже)
        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(180));
        context.drawTexture(arrowTexture, -iconSize / 2, -iconSize / 2, iconSize, iconSize, markerIconColor.getColor());
        context.popMatrix();

        // Рисуем текст
        context.drawText(font, gpsText, posX - gpsWidth / 2, rectY + 3 * markerSize.getCurrent(), color);
        context.drawText(font, distText, posX - distWidth / 2, rectY + 3 * markerSize.getCurrent() + font.height() + 2,
                color);

        context.popMatrix();
    }
}
А кстати вопрос как вы блин редачите зенит рекод? там же файлы онли для просмотра
 
Решил сделать, так-же полу вайб код, старался, но для пастерков нямка нямка, буду рад отзывам, делаю стараюсь :(
старался если что не бейте, имеет баг визуальный что две метки одна вертикальная другой, но если что 3д метку выключить можно, хз как фиксить, кто шарит подскажите пожалуйста

ss:
Пожалуйста, авторизуйтесь для просмотра ссылки.


.gps test можете

GPS.java:
Expand Collapse Copy
package zenith.zov.client.modules.impl.render;

import com.darkmagician6.eventapi.EventTarget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zenith.zov.Zenith;
import zenith.zov.base.events.impl.server.EventPacket;
import zenith.zov.base.events.impl.render.EventHudRender;
import zenith.zov.client.hud.elements.component.EventFTComponent;
import zenith.zov.base.font.Font;
import zenith.zov.base.font.Fonts;
import zenith.zov.base.theme.Theme;
import zenith.zov.client.modules.api.Category;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.api.ModuleAnnotation;
import zenith.zov.client.modules.api.setting.impl.BooleanSetting;
import zenith.zov.client.modules.api.setting.impl.ModeSetting;
import zenith.zov.client.modules.api.setting.impl.NumberSetting;
import zenith.zov.utility.render.display.base.CustomDrawContext;
import zenith.zov.utility.render.display.base.BorderRadius;
import zenith.zov.utility.render.display.shader.DrawUtil;
import zenith.zov.utility.math.ProjectionUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@ModuleAnnotation(name = "GPS", description = "Показывает стрелку к заданным координатам", category = Category.RENDER)
public class GPS extends Module {
    public static final GPS INSTANCE = new GPS();

    private GPS() {
    }

    private final NumberSetting distanceFromCenter = new NumberSetting("Дистанция от центра", 50, 30, 150, 5);
    private final NumberSetting arrowSize = new NumberSetting("Размер стрелки", 32, 16, 64, 2);
    private final NumberSetting markerSize = new NumberSetting("Размер метки 3D", 1.5f, 0.5f, 3f, 0.1f);
    private final BooleanSetting showDistance = new BooleanSetting("Показывать дистанцию", true);
    private final BooleanSetting show3DMarker = new BooleanSetting("Показывать 3D метку", true);
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting arrowColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет стрелки HUD", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting markerIconColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет иконки метки", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 100, 100, 255));

    private final BooleanSetting autoGPS = new BooleanSetting("АвтоGPS", false);
    private final ModeSetting autoGPSMode = new ModeSetting("Режим", autoGPS::isEnabled);
    private final ModeSetting.Value funtime = new ModeSetting.Value(autoGPSMode, "Funtime").select();

    private final Identifier arrowTexture = Zenith.id("icons/gps_arrow.png");

    private static double targetX = 0;
    private static double targetY = 0;
    private static double targetZ = 0;
    private static boolean hasTarget = false;
    private static String lastEventName = "";

    private float smoothAngle = 0;
    private double smoothArrowX = 0;
    private double smoothArrowY = 0;

    private static final Pattern METEOR_PATTERN = Pattern
            .compile("Метеоритный дождь.*?\\[(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)\\]");
    private static final Pattern VOLCANO_PATTERN = Pattern
            .compile("Вулкан.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern KILLER_BEACON_PATTERN = Pattern
            .compile("Маяк убийца.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern DEATH_CHEST_PATTERN = Pattern
            .compile("Сундук Смерти.*?Появится уже через (\\d+) минут");
    private static final Pattern EVENT_STARTED_PATTERN = Pattern
            .compile("(Портал на резню активирован|Идёт страшный бой)");

    public static void setTarget(double x, double y, double z) {
        setTarget(x, y, z, "");
    }

    public static void setTarget(double x, double y, double z, String eventName) {
        targetX = x;
        targetY = y;
        targetZ = z;
        hasTarget = true;
        lastEventName = eventName;
    }

    public static void clearTarget() {
        hasTarget = false;
        lastEventName = "";
    }

    public static boolean hasTarget() {
        return hasTarget;
    }

    public static String getLastEventName() {
        return lastEventName;
    }

    public static double getTargetX() {
        return targetX;
    }

    public static double getTargetY() {
        return targetY;
    }

    public static double getTargetZ() {
        return targetZ;
    }

    @EventTarget
    public void onHudRender(EventHudRender event) {
        if (mc.player == null || mc.world == null || !hasTarget)
            return;

        CustomDrawContext ctx = event.getContext();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();
        Font font = Fonts.MEDIUM.getFont(5);

        float centerX = ctx.getScaledWindowWidth() / 2f;
        float centerY = ctx.getScaledWindowHeight() / 2f;

        double playerX = mc.player.getX();
        double playerZ = mc.player.getZ();

        double deltaX = targetX - playerX;
        double deltaZ = targetZ - playerZ;

        double distance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);

        float yaw = mc.player.getYaw();
        double yawRad = Math.toRadians(yaw);

        double cos = Math.cos(yawRad);
        double sin = Math.sin(yawRad);

        double rotY = -(deltaZ * cos - deltaX * sin);
        double rotX = -(deltaX * cos + deltaZ * sin);

        if (Math.abs(rotX) < 0.01 && Math.abs(rotY) < 0.01)
            return;

        float targetAngle = (float) (Math.atan2(rotY, rotX) * 180 / Math.PI);

        // Плавная интерполяция угла
        float angleDiff = targetAngle - smoothAngle;
        while (angleDiff > 180)
            angleDiff -= 360;
        while (angleDiff < -180)
            angleDiff += 360;
        smoothAngle += angleDiff * 0.3f;

        double targetArrowX = distanceFromCenter.getCurrent() * MathHelper.cos((float) Math.toRadians(targetAngle))
                + centerX;
        double targetArrowY = distanceFromCenter.getCurrent() * MathHelper.sin((float) Math.toRadians(targetAngle))
                + centerY;

        // Плавная интерполяция позиции
        smoothArrowX += (targetArrowX - smoothArrowX) * 0.3;
        smoothArrowY += (targetArrowY - smoothArrowY) * 0.3;

        float size = arrowSize.getCurrent();

        ctx.pushMatrix();
        ctx.getMatrices().translate(smoothArrowX, smoothArrowY, 0);
        ctx.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(smoothAngle + 90));
        ctx.getMatrices().translate(-size / 2, -size / 2, 0);

        zenith.zov.utility.render.display.base.color.ColorRGBA arrowColor = getArrowColor();
        ctx.drawTexture(arrowTexture, 0, 0, size, size, arrowColor);

        ctx.popMatrix();

        if (showDistance.isEnabled()) {
            String distanceText = String.format("%.0f", distance);
            float textWidth = font.width(distanceText);

            float textAngleRad = (float) Math.toRadians(smoothAngle);
            float textX = (float) smoothArrowX + MathHelper.cos(textAngleRad) * (size / 2 + 5);
            float textY = (float) smoothArrowY + MathHelper.sin(textAngleRad) * (size / 2 + 5);

            ctx.drawText(font, distanceText, textX - textWidth / 2, textY - font.height() / 2, getArrowColor());
        }
    }

    private zenith.zov.utility.render.display.base.color.ColorRGBA getArrowColor() {
        return arrowColor.getColor();
    }

    public static void processMessage(String message) {
        if (!INSTANCE.autoGPS.isEnabled() || mc.player == null) return;
       
        // Убираем все цветовые коды, форматирование и невидимые символы
        String cleanMessage = message
                .replaceAll("§[0-9a-fk-or]", "") // Minecraft цвета
                .replaceAll("&[0-9a-fk-or]", "") // Альтернативные цвета
                .replaceAll("[\\x00-\\x1F\\x7F]", "") // Управляющие символы
                .replaceAll("\\p{C}", ""); // Все невидимые Unicode символы

        if (INSTANCE.funtime.isSelected()) {
            // Проверяем начало ивента (портал активирован / идёт бой = выключаем GPS)
            Matcher eventStartedMatcher = EVENT_STARTED_PATTERN.matcher(cleanMessage);
            if (eventStartedMatcher.find()) {
                clearTarget();
                if (mc.player != null) {
                    mc.player.sendMessage(
                            Text.literal("§cGPS метка снята - §6Ивент начался!"),
                            true);
                }
                return;
            }
           
            // Проверяем сундук смерти (появится через 3 минуты = выключаем GPS)
            Matcher deathChestMatcher = DEATH_CHEST_PATTERN.matcher(cleanMessage);
            if (deathChestMatcher.find()) {
                try {
                    int minutes = Integer.parseInt(deathChestMatcher.group(1));
                    if (minutes == 3) {
                        clearTarget();
                        if (mc.player != null) {
                            mc.player.sendMessage(
                                    Text.literal("§cGPS метка снята - §6Сундук Смерти §cпоявится через 3 минуты"),
                                    true);
                        }
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }

            // Ищем паттерн метеоритного дождя
            Matcher meteorMatcher = METEOR_PATTERN.matcher(cleanMessage);
            if (meteorMatcher.find()) {
                try {
                    int x = Integer.parseInt(meteorMatcher.group(1));
                    int y = Integer.parseInt(meteorMatcher.group(2));
                    int z = Integer.parseInt(meteorMatcher.group(3));

                    setTarget(x, y, z, "Метеоритный дождь");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Метеоритный дождь"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
           
            // Ищем паттерн вулкана
            Matcher volcanoMatcher = VOLCANO_PATTERN.matcher(cleanMessage);
            if (volcanoMatcher.find()) {
                try {
                    int x = Integer.parseInt(volcanoMatcher.group(1));
                    int y = Integer.parseInt(volcanoMatcher.group(2));
                    int z = Integer.parseInt(volcanoMatcher.group(3));

                    setTarget(x, y, z, "Вулкан");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Вулкан"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
           
            // Ищем паттерн маяка убийцы
            Matcher killerBeaconMatcher = KILLER_BEACON_PATTERN.matcher(cleanMessage);
            if (killerBeaconMatcher.find()) {
                try {
                    int x = Integer.parseInt(killerBeaconMatcher.group(1));
                    int y = Integer.parseInt(killerBeaconMatcher.group(2));
                    int z = Integer.parseInt(killerBeaconMatcher.group(3));

                    setTarget(x, y, z, "Маяк убийца");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Маяк убийца"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
            }
        }
       
        // Обрабатываем сообщения для EventFTComponent
        EventFTComponent.processEventMessage(message);
    }
   
    @EventTarget
    public void onPacket(EventPacket event) {
        if (mc.player == null || !event.isReceive())
            return;

        // Обрабатываем сообщения для автоGPS
        if (autoGPS.isEnabled() && event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameMessageS2CPacket packet) {
            processMessage(packet.content().getString());
        }
       
        // Отслеживаем заход на сервер (GameJoinS2CPacket)
        if (event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameJoinS2CPacket) {
            EventFTComponent.onServerJoin();
        }
    }

    @EventTarget
    public void onRender2D(zenith.zov.base.events.impl.render.EventRender2D event) {
        if (mc.player == null || mc.world == null || !hasTarget || !show3DMarker.isEnabled())
            return;

        double playerX = mc.player.getX();
        double playerY = mc.player.getY();
        double playerZ = mc.player.getZ();

        double distance = Math.sqrt((targetX - playerX) * (targetX - playerX)
                + (targetY - playerY) * (targetY - playerY) + (targetZ - playerZ) * (targetZ - playerZ));

        // Получаем проекцию точки на экран
        Vec3d targetPos = new Vec3d(targetX, targetY, targetZ);
        Vec3d projected = ProjectionUtil.worldSpaceToScreenSpace(targetPos);

        CustomDrawContext context = event.getContext();
        Font font = Fonts.MEDIUM.getFont(8 * markerSize.getCurrent());
        zenith.zov.utility.render.display.base.color.ColorRGBA color = getArrowColor();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();

        float posX = (float) projected.x;
        float posY = (float) projected.y;

        // Размеры иконки
        float iconSize = 16 * markerSize.getCurrent();

        // Текст
        String gpsText = "GPS";
        String distText = String.format("%.0fm", distance);
        float gpsWidth = font.width(gpsText);
        float distWidth = font.width(distText);
        float maxTextWidth = Math.max(gpsWidth, distWidth);

        // Размеры прямоугольника
        float rectWidth = maxTextWidth + 16 * markerSize.getCurrent();
        float rectHeight = (font.height() * 2 + 6) * markerSize.getCurrent();
        float rectX = posX - rectWidth / 2;
        float rectY = posY + iconSize + 4 * markerSize.getCurrent();

        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().scale(markerSize.getCurrent(), markerSize.getCurrent(), 1f);
        context.getMatrices().translate(-posX, -posY, 0);

        // Рисуем фон для текста
        DrawUtil.drawBlurHud(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 22, BorderRadius.all(2),
                new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
        context.drawRoundedRect(rectX, rectY, rectWidth, rectHeight, BorderRadius.all(2), theme.getForegroundLight());
        DrawUtil.drawRoundedCorner(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 0.1f, 9, color,
                BorderRadius.all(2));

        // Рисуем иконку стрелки (перевернутую вниз, чуть ниже)
        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(180));
        context.drawTexture(arrowTexture, -iconSize / 2, -iconSize / 2, iconSize, iconSize, markerIconColor.getColor());
        context.popMatrix();

        // Рисуем текст
        context.drawText(font, gpsText, posX - gpsWidth / 2, rectY + 3 * markerSize.getCurrent(), color);
        context.drawText(font, distText, posX - distWidth / 2, rectY + 3 * markerSize.getCurrent() + font.height() + 2,
                color);

        context.popMatrix();
    }
}
говно ебанное
 
А что он делает?

А кстати вопрос как вы блин редачите зенит рекод? там же файлы онли для просмотра
братик чтобы у тебя были файлы не онли для просмотра нужно открывать не папку build а заходить в папку src и так далее
 
Решил сделать, так-же полу вайб код, старался, но для пастерков нямка нямка, буду рад отзывам, делаю стараюсь :(
старался если что не бейте, имеет баг визуальный что две метки одна вертикальная другой, но если что 3д метку выключить можно, хз как фиксить, кто шарит подскажите пожалуйста

ss:
Пожалуйста, авторизуйтесь для просмотра ссылки.


.gps test можете

GPS.java:
Expand Collapse Copy
package zenith.zov.client.modules.impl.render;

import com.darkmagician6.eventapi.EventTarget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zenith.zov.Zenith;
import zenith.zov.base.events.impl.server.EventPacket;
import zenith.zov.base.events.impl.render.EventHudRender;
import zenith.zov.client.hud.elements.component.EventFTComponent;
import zenith.zov.base.font.Font;
import zenith.zov.base.font.Fonts;
import zenith.zov.base.theme.Theme;
import zenith.zov.client.modules.api.Category;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.api.ModuleAnnotation;
import zenith.zov.client.modules.api.setting.impl.BooleanSetting;
import zenith.zov.client.modules.api.setting.impl.ModeSetting;
import zenith.zov.client.modules.api.setting.impl.NumberSetting;
import zenith.zov.utility.render.display.base.CustomDrawContext;
import zenith.zov.utility.render.display.base.BorderRadius;
import zenith.zov.utility.render.display.shader.DrawUtil;
import zenith.zov.utility.math.ProjectionUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@ModuleAnnotation(name = "GPS", description = "Показывает стрелку к заданным координатам", category = Category.RENDER)
public class GPS extends Module {
    public static final GPS INSTANCE = new GPS();

    private GPS() {
    }

    private final NumberSetting distanceFromCenter = new NumberSetting("Дистанция от центра", 50, 30, 150, 5);
    private final NumberSetting arrowSize = new NumberSetting("Размер стрелки", 32, 16, 64, 2);
    private final NumberSetting markerSize = new NumberSetting("Размер метки 3D", 1.5f, 0.5f, 3f, 0.1f);
    private final BooleanSetting showDistance = new BooleanSetting("Показывать дистанцию", true);
    private final BooleanSetting show3DMarker = new BooleanSetting("Показывать 3D метку", true);
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting arrowColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет стрелки HUD", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting markerIconColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет иконки метки", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 100, 100, 255));

    private final BooleanSetting autoGPS = new BooleanSetting("АвтоGPS", false);
    private final ModeSetting autoGPSMode = new ModeSetting("Режим", autoGPS::isEnabled);
    private final ModeSetting.Value funtime = new ModeSetting.Value(autoGPSMode, "Funtime").select();

    private final Identifier arrowTexture = Zenith.id("icons/gps_arrow.png");

    private static double targetX = 0;
    private static double targetY = 0;
    private static double targetZ = 0;
    private static boolean hasTarget = false;
    private static String lastEventName = "";

    private float smoothAngle = 0;
    private double smoothArrowX = 0;
    private double smoothArrowY = 0;

    private static final Pattern METEOR_PATTERN = Pattern
            .compile("Метеоритный дождь.*?\\[(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)\\]");
    private static final Pattern VOLCANO_PATTERN = Pattern
            .compile("Вулкан.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern KILLER_BEACON_PATTERN = Pattern
            .compile("Маяк убийца.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern DEATH_CHEST_PATTERN = Pattern
            .compile("Сундук Смерти.*?Появится уже через (\\d+) минут");
    private static final Pattern EVENT_STARTED_PATTERN = Pattern
            .compile("(Портал на резню активирован|Идёт страшный бой)");

    public static void setTarget(double x, double y, double z) {
        setTarget(x, y, z, "");
    }

    public static void setTarget(double x, double y, double z, String eventName) {
        targetX = x;
        targetY = y;
        targetZ = z;
        hasTarget = true;
        lastEventName = eventName;
    }

    public static void clearTarget() {
        hasTarget = false;
        lastEventName = "";
    }

    public static boolean hasTarget() {
        return hasTarget;
    }

    public static String getLastEventName() {
        return lastEventName;
    }

    public static double getTargetX() {
        return targetX;
    }

    public static double getTargetY() {
        return targetY;
    }

    public static double getTargetZ() {
        return targetZ;
    }

    @EventTarget
    public void onHudRender(EventHudRender event) {
        if (mc.player == null || mc.world == null || !hasTarget)
            return;

        CustomDrawContext ctx = event.getContext();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();
        Font font = Fonts.MEDIUM.getFont(5);

        float centerX = ctx.getScaledWindowWidth() / 2f;
        float centerY = ctx.getScaledWindowHeight() / 2f;

        double playerX = mc.player.getX();
        double playerZ = mc.player.getZ();

        double deltaX = targetX - playerX;
        double deltaZ = targetZ - playerZ;

        double distance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);

        float yaw = mc.player.getYaw();
        double yawRad = Math.toRadians(yaw);

        double cos = Math.cos(yawRad);
        double sin = Math.sin(yawRad);

        double rotY = -(deltaZ * cos - deltaX * sin);
        double rotX = -(deltaX * cos + deltaZ * sin);

        if (Math.abs(rotX) < 0.01 && Math.abs(rotY) < 0.01)
            return;

        float targetAngle = (float) (Math.atan2(rotY, rotX) * 180 / Math.PI);

        // Плавная интерполяция угла
        float angleDiff = targetAngle - smoothAngle;
        while (angleDiff > 180)
            angleDiff -= 360;
        while (angleDiff < -180)
            angleDiff += 360;
        smoothAngle += angleDiff * 0.3f;

        double targetArrowX = distanceFromCenter.getCurrent() * MathHelper.cos((float) Math.toRadians(targetAngle))
                + centerX;
        double targetArrowY = distanceFromCenter.getCurrent() * MathHelper.sin((float) Math.toRadians(targetAngle))
                + centerY;

        // Плавная интерполяция позиции
        smoothArrowX += (targetArrowX - smoothArrowX) * 0.3;
        smoothArrowY += (targetArrowY - smoothArrowY) * 0.3;

        float size = arrowSize.getCurrent();

        ctx.pushMatrix();
        ctx.getMatrices().translate(smoothArrowX, smoothArrowY, 0);
        ctx.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(smoothAngle + 90));
        ctx.getMatrices().translate(-size / 2, -size / 2, 0);

        zenith.zov.utility.render.display.base.color.ColorRGBA arrowColor = getArrowColor();
        ctx.drawTexture(arrowTexture, 0, 0, size, size, arrowColor);

        ctx.popMatrix();

        if (showDistance.isEnabled()) {
            String distanceText = String.format("%.0f", distance);
            float textWidth = font.width(distanceText);

            float textAngleRad = (float) Math.toRadians(smoothAngle);
            float textX = (float) smoothArrowX + MathHelper.cos(textAngleRad) * (size / 2 + 5);
            float textY = (float) smoothArrowY + MathHelper.sin(textAngleRad) * (size / 2 + 5);

            ctx.drawText(font, distanceText, textX - textWidth / 2, textY - font.height() / 2, getArrowColor());
        }
    }

    private zenith.zov.utility.render.display.base.color.ColorRGBA getArrowColor() {
        return arrowColor.getColor();
    }

    public static void processMessage(String message) {
        if (!INSTANCE.autoGPS.isEnabled() || mc.player == null) return;
       
        // Убираем все цветовые коды, форматирование и невидимые символы
        String cleanMessage = message
                .replaceAll("§[0-9a-fk-or]", "") // Minecraft цвета
                .replaceAll("&[0-9a-fk-or]", "") // Альтернативные цвета
                .replaceAll("[\\x00-\\x1F\\x7F]", "") // Управляющие символы
                .replaceAll("\\p{C}", ""); // Все невидимые Unicode символы

        if (INSTANCE.funtime.isSelected()) {
            // Проверяем начало ивента (портал активирован / идёт бой = выключаем GPS)
            Matcher eventStartedMatcher = EVENT_STARTED_PATTERN.matcher(cleanMessage);
            if (eventStartedMatcher.find()) {
                clearTarget();
                if (mc.player != null) {
                    mc.player.sendMessage(
                            Text.literal("§cGPS метка снята - §6Ивент начался!"),
                            true);
                }
                return;
            }
           
            // Проверяем сундук смерти (появится через 3 минуты = выключаем GPS)
            Matcher deathChestMatcher = DEATH_CHEST_PATTERN.matcher(cleanMessage);
            if (deathChestMatcher.find()) {
                try {
                    int minutes = Integer.parseInt(deathChestMatcher.group(1));
                    if (minutes == 3) {
                        clearTarget();
                        if (mc.player != null) {
                            mc.player.sendMessage(
                                    Text.literal("§cGPS метка снята - §6Сундук Смерти §cпоявится через 3 минуты"),
                                    true);
                        }
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }

            // Ищем паттерн метеоритного дождя
            Matcher meteorMatcher = METEOR_PATTERN.matcher(cleanMessage);
            if (meteorMatcher.find()) {
                try {
                    int x = Integer.parseInt(meteorMatcher.group(1));
                    int y = Integer.parseInt(meteorMatcher.group(2));
                    int z = Integer.parseInt(meteorMatcher.group(3));

                    setTarget(x, y, z, "Метеоритный дождь");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Метеоритный дождь"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
           
            // Ищем паттерн вулкана
            Matcher volcanoMatcher = VOLCANO_PATTERN.matcher(cleanMessage);
            if (volcanoMatcher.find()) {
                try {
                    int x = Integer.parseInt(volcanoMatcher.group(1));
                    int y = Integer.parseInt(volcanoMatcher.group(2));
                    int z = Integer.parseInt(volcanoMatcher.group(3));

                    setTarget(x, y, z, "Вулкан");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Вулкан"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
           
            // Ищем паттерн маяка убийцы
            Matcher killerBeaconMatcher = KILLER_BEACON_PATTERN.matcher(cleanMessage);
            if (killerBeaconMatcher.find()) {
                try {
                    int x = Integer.parseInt(killerBeaconMatcher.group(1));
                    int y = Integer.parseInt(killerBeaconMatcher.group(2));
                    int z = Integer.parseInt(killerBeaconMatcher.group(3));

                    setTarget(x, y, z, "Маяк убийца");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Маяк убийца"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
            }
        }
       
        // Обрабатываем сообщения для EventFTComponent
        EventFTComponent.processEventMessage(message);
    }
   
    @EventTarget
    public void onPacket(EventPacket event) {
        if (mc.player == null || !event.isReceive())
            return;

        // Обрабатываем сообщения для автоGPS
        if (autoGPS.isEnabled() && event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameMessageS2CPacket packet) {
            processMessage(packet.content().getString());
        }
       
        // Отслеживаем заход на сервер (GameJoinS2CPacket)
        if (event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameJoinS2CPacket) {
            EventFTComponent.onServerJoin();
        }
    }

    @EventTarget
    public void onRender2D(zenith.zov.base.events.impl.render.EventRender2D event) {
        if (mc.player == null || mc.world == null || !hasTarget || !show3DMarker.isEnabled())
            return;

        double playerX = mc.player.getX();
        double playerY = mc.player.getY();
        double playerZ = mc.player.getZ();

        double distance = Math.sqrt((targetX - playerX) * (targetX - playerX)
                + (targetY - playerY) * (targetY - playerY) + (targetZ - playerZ) * (targetZ - playerZ));

        // Получаем проекцию точки на экран
        Vec3d targetPos = new Vec3d(targetX, targetY, targetZ);
        Vec3d projected = ProjectionUtil.worldSpaceToScreenSpace(targetPos);

        CustomDrawContext context = event.getContext();
        Font font = Fonts.MEDIUM.getFont(8 * markerSize.getCurrent());
        zenith.zov.utility.render.display.base.color.ColorRGBA color = getArrowColor();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();

        float posX = (float) projected.x;
        float posY = (float) projected.y;

        // Размеры иконки
        float iconSize = 16 * markerSize.getCurrent();

        // Текст
        String gpsText = "GPS";
        String distText = String.format("%.0fm", distance);
        float gpsWidth = font.width(gpsText);
        float distWidth = font.width(distText);
        float maxTextWidth = Math.max(gpsWidth, distWidth);

        // Размеры прямоугольника
        float rectWidth = maxTextWidth + 16 * markerSize.getCurrent();
        float rectHeight = (font.height() * 2 + 6) * markerSize.getCurrent();
        float rectX = posX - rectWidth / 2;
        float rectY = posY + iconSize + 4 * markerSize.getCurrent();

        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().scale(markerSize.getCurrent(), markerSize.getCurrent(), 1f);
        context.getMatrices().translate(-posX, -posY, 0);

        // Рисуем фон для текста
        DrawUtil.drawBlurHud(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 22, BorderRadius.all(2),
                new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
        context.drawRoundedRect(rectX, rectY, rectWidth, rectHeight, BorderRadius.all(2), theme.getForegroundLight());
        DrawUtil.drawRoundedCorner(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 0.1f, 9, color,
                BorderRadius.all(2));

        // Рисуем иконку стрелки (перевернутую вниз, чуть ниже)
        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(180));
        context.drawTexture(arrowTexture, -iconSize / 2, -iconSize / 2, iconSize, iconSize, markerIconColor.getColor());
        context.popMatrix();

        // Рисуем текст
        context.drawText(font, gpsText, posX - gpsWidth / 2, rectY + 3 * markerSize.getCurrent(), color);
        context.drawText(font, distText, posX - distWidth / 2, rectY + 3 * markerSize.getCurrent() + font.height() + 2,
                color);

        context.popMatrix();
    }
}
Пиздец нахуй, дожили, гпс отдельным модулем :D
 
братик чтобы у тебя были файлы не онли для просмотра нужно открывать не папку build а заходить в папку src и так далее
брух я захожу в срц и там все онли для просмотра
 
Решил сделать, так-же полу вайб код, старался, но для пастерков нямка нямка, буду рад отзывам, делаю стараюсь :(
старался если что не бейте, имеет баг визуальный что две метки одна вертикальная другой, но если что 3д метку выключить можно, хз как фиксить, кто шарит подскажите пожалуйста

ss:
Пожалуйста, авторизуйтесь для просмотра ссылки.


.gps test можете

GPS.java:
Expand Collapse Copy
package zenith.zov.client.modules.impl.render;

import com.darkmagician6.eventapi.EventTarget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import zenith.zov.Zenith;
import zenith.zov.base.events.impl.server.EventPacket;
import zenith.zov.base.events.impl.render.EventHudRender;
import zenith.zov.client.hud.elements.component.EventFTComponent;
import zenith.zov.base.font.Font;
import zenith.zov.base.font.Fonts;
import zenith.zov.base.theme.Theme;
import zenith.zov.client.modules.api.Category;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.api.ModuleAnnotation;
import zenith.zov.client.modules.api.setting.impl.BooleanSetting;
import zenith.zov.client.modules.api.setting.impl.ModeSetting;
import zenith.zov.client.modules.api.setting.impl.NumberSetting;
import zenith.zov.utility.render.display.base.CustomDrawContext;
import zenith.zov.utility.render.display.base.BorderRadius;
import zenith.zov.utility.render.display.shader.DrawUtil;
import zenith.zov.utility.math.ProjectionUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@ModuleAnnotation(name = "GPS", description = "Показывает стрелку к заданным координатам", category = Category.RENDER)
public class GPS extends Module {
    public static final GPS INSTANCE = new GPS();

    private GPS() {
    }

    private final NumberSetting distanceFromCenter = new NumberSetting("Дистанция от центра", 50, 30, 150, 5);
    private final NumberSetting arrowSize = new NumberSetting("Размер стрелки", 32, 16, 64, 2);
    private final NumberSetting markerSize = new NumberSetting("Размер метки 3D", 1.5f, 0.5f, 3f, 0.1f);
    private final BooleanSetting showDistance = new BooleanSetting("Показывать дистанцию", true);
    private final BooleanSetting show3DMarker = new BooleanSetting("Показывать 3D метку", true);
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting arrowColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет стрелки HUD", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
    private final zenith.zov.client.modules.api.setting.impl.ColorSetting markerIconColor = new zenith.zov.client.modules.api.setting.impl.ColorSetting(
            "Цвет иконки метки", new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 100, 100, 255));

    private final BooleanSetting autoGPS = new BooleanSetting("АвтоGPS", false);
    private final ModeSetting autoGPSMode = new ModeSetting("Режим", autoGPS::isEnabled);
    private final ModeSetting.Value funtime = new ModeSetting.Value(autoGPSMode, "Funtime").select();

    private final Identifier arrowTexture = Zenith.id("icons/gps_arrow.png");

    private static double targetX = 0;
    private static double targetY = 0;
    private static double targetZ = 0;
    private static boolean hasTarget = false;
    private static String lastEventName = "";

    private float smoothAngle = 0;
    private double smoothArrowX = 0;
    private double smoothArrowY = 0;

    private static final Pattern METEOR_PATTERN = Pattern
            .compile("Метеоритный дождь.*?\\[(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)\\]");
    private static final Pattern VOLCANO_PATTERN = Pattern
            .compile("Вулкан.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern KILLER_BEACON_PATTERN = Pattern
            .compile("Маяк убийца.*?(-?\\d+)\\s+(\\d+)\\s+(-?\\d+)");
    private static final Pattern DEATH_CHEST_PATTERN = Pattern
            .compile("Сундук Смерти.*?Появится уже через (\\d+) минут");
    private static final Pattern EVENT_STARTED_PATTERN = Pattern
            .compile("(Портал на резню активирован|Идёт страшный бой)");

    public static void setTarget(double x, double y, double z) {
        setTarget(x, y, z, "");
    }

    public static void setTarget(double x, double y, double z, String eventName) {
        targetX = x;
        targetY = y;
        targetZ = z;
        hasTarget = true;
        lastEventName = eventName;
    }

    public static void clearTarget() {
        hasTarget = false;
        lastEventName = "";
    }

    public static boolean hasTarget() {
        return hasTarget;
    }

    public static String getLastEventName() {
        return lastEventName;
    }

    public static double getTargetX() {
        return targetX;
    }

    public static double getTargetY() {
        return targetY;
    }

    public static double getTargetZ() {
        return targetZ;
    }

    @EventTarget
    public void onHudRender(EventHudRender event) {
        if (mc.player == null || mc.world == null || !hasTarget)
            return;

        CustomDrawContext ctx = event.getContext();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();
        Font font = Fonts.MEDIUM.getFont(5);

        float centerX = ctx.getScaledWindowWidth() / 2f;
        float centerY = ctx.getScaledWindowHeight() / 2f;

        double playerX = mc.player.getX();
        double playerZ = mc.player.getZ();

        double deltaX = targetX - playerX;
        double deltaZ = targetZ - playerZ;

        double distance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);

        float yaw = mc.player.getYaw();
        double yawRad = Math.toRadians(yaw);

        double cos = Math.cos(yawRad);
        double sin = Math.sin(yawRad);

        double rotY = -(deltaZ * cos - deltaX * sin);
        double rotX = -(deltaX * cos + deltaZ * sin);

        if (Math.abs(rotX) < 0.01 && Math.abs(rotY) < 0.01)
            return;

        float targetAngle = (float) (Math.atan2(rotY, rotX) * 180 / Math.PI);

        // Плавная интерполяция угла
        float angleDiff = targetAngle - smoothAngle;
        while (angleDiff > 180)
            angleDiff -= 360;
        while (angleDiff < -180)
            angleDiff += 360;
        smoothAngle += angleDiff * 0.3f;

        double targetArrowX = distanceFromCenter.getCurrent() * MathHelper.cos((float) Math.toRadians(targetAngle))
                + centerX;
        double targetArrowY = distanceFromCenter.getCurrent() * MathHelper.sin((float) Math.toRadians(targetAngle))
                + centerY;

        // Плавная интерполяция позиции
        smoothArrowX += (targetArrowX - smoothArrowX) * 0.3;
        smoothArrowY += (targetArrowY - smoothArrowY) * 0.3;

        float size = arrowSize.getCurrent();

        ctx.pushMatrix();
        ctx.getMatrices().translate(smoothArrowX, smoothArrowY, 0);
        ctx.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(smoothAngle + 90));
        ctx.getMatrices().translate(-size / 2, -size / 2, 0);

        zenith.zov.utility.render.display.base.color.ColorRGBA arrowColor = getArrowColor();
        ctx.drawTexture(arrowTexture, 0, 0, size, size, arrowColor);

        ctx.popMatrix();

        if (showDistance.isEnabled()) {
            String distanceText = String.format("%.0f", distance);
            float textWidth = font.width(distanceText);

            float textAngleRad = (float) Math.toRadians(smoothAngle);
            float textX = (float) smoothArrowX + MathHelper.cos(textAngleRad) * (size / 2 + 5);
            float textY = (float) smoothArrowY + MathHelper.sin(textAngleRad) * (size / 2 + 5);

            ctx.drawText(font, distanceText, textX - textWidth / 2, textY - font.height() / 2, getArrowColor());
        }
    }

    private zenith.zov.utility.render.display.base.color.ColorRGBA getArrowColor() {
        return arrowColor.getColor();
    }

    public static void processMessage(String message) {
        if (!INSTANCE.autoGPS.isEnabled() || mc.player == null) return;
      
        // Убираем все цветовые коды, форматирование и невидимые символы
        String cleanMessage = message
                .replaceAll("§[0-9a-fk-or]", "") // Minecraft цвета
                .replaceAll("&[0-9a-fk-or]", "") // Альтернативные цвета
                .replaceAll("[\\x00-\\x1F\\x7F]", "") // Управляющие символы
                .replaceAll("\\p{C}", ""); // Все невидимые Unicode символы

        if (INSTANCE.funtime.isSelected()) {
            // Проверяем начало ивента (портал активирован / идёт бой = выключаем GPS)
            Matcher eventStartedMatcher = EVENT_STARTED_PATTERN.matcher(cleanMessage);
            if (eventStartedMatcher.find()) {
                clearTarget();
                if (mc.player != null) {
                    mc.player.sendMessage(
                            Text.literal("§cGPS метка снята - §6Ивент начался!"),
                            true);
                }
                return;
            }
          
            // Проверяем сундук смерти (появится через 3 минуты = выключаем GPS)
            Matcher deathChestMatcher = DEATH_CHEST_PATTERN.matcher(cleanMessage);
            if (deathChestMatcher.find()) {
                try {
                    int minutes = Integer.parseInt(deathChestMatcher.group(1));
                    if (minutes == 3) {
                        clearTarget();
                        if (mc.player != null) {
                            mc.player.sendMessage(
                                    Text.literal("§cGPS метка снята - §6Сундук Смерти §cпоявится через 3 минуты"),
                                    true);
                        }
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }

            // Ищем паттерн метеоритного дождя
            Matcher meteorMatcher = METEOR_PATTERN.matcher(cleanMessage);
            if (meteorMatcher.find()) {
                try {
                    int x = Integer.parseInt(meteorMatcher.group(1));
                    int y = Integer.parseInt(meteorMatcher.group(2));
                    int z = Integer.parseInt(meteorMatcher.group(3));

                    setTarget(x, y, z, "Метеоритный дождь");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Метеоритный дождь"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
          
            // Ищем паттерн вулкана
            Matcher volcanoMatcher = VOLCANO_PATTERN.matcher(cleanMessage);
            if (volcanoMatcher.find()) {
                try {
                    int x = Integer.parseInt(volcanoMatcher.group(1));
                    int y = Integer.parseInt(volcanoMatcher.group(2));
                    int z = Integer.parseInt(volcanoMatcher.group(3));

                    setTarget(x, y, z, "Вулкан");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Вулкан"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
                return;
            }
          
            // Ищем паттерн маяка убийцы
            Matcher killerBeaconMatcher = KILLER_BEACON_PATTERN.matcher(cleanMessage);
            if (killerBeaconMatcher.find()) {
                try {
                    int x = Integer.parseInt(killerBeaconMatcher.group(1));
                    int y = Integer.parseInt(killerBeaconMatcher.group(2));
                    int z = Integer.parseInt(killerBeaconMatcher.group(3));

                    setTarget(x, y, z, "Маяк убийца");

                    // Показываем уведомление в ActionBar
                    if (mc.player != null) {
                        mc.player.sendMessage(Text.literal("§aGPS метка установлена на §e[" + x + " " + y + " " + z
                                + "]§a от события §6Маяк убийца"), true);
                    }
                } catch (NumberFormatException e) {
                    // Игнорируем ошибки парсинга
                }
            }
        }
      
        // Обрабатываем сообщения для EventFTComponent
        EventFTComponent.processEventMessage(message);
    }
  
    @EventTarget
    public void onPacket(EventPacket event) {
        if (mc.player == null || !event.isReceive())
            return;

        // Обрабатываем сообщения для автоGPS
        if (autoGPS.isEnabled() && event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameMessageS2CPacket packet) {
            processMessage(packet.content().getString());
        }
      
        // Отслеживаем заход на сервер (GameJoinS2CPacket)
        if (event.getPacket() instanceof net.minecraft.network.packet.s2c.play.GameJoinS2CPacket) {
            EventFTComponent.onServerJoin();
        }
    }

    @EventTarget
    public void onRender2D(zenith.zov.base.events.impl.render.EventRender2D event) {
        if (mc.player == null || mc.world == null || !hasTarget || !show3DMarker.isEnabled())
            return;

        double playerX = mc.player.getX();
        double playerY = mc.player.getY();
        double playerZ = mc.player.getZ();

        double distance = Math.sqrt((targetX - playerX) * (targetX - playerX)
                + (targetY - playerY) * (targetY - playerY) + (targetZ - playerZ) * (targetZ - playerZ));

        // Получаем проекцию точки на экран
        Vec3d targetPos = new Vec3d(targetX, targetY, targetZ);
        Vec3d projected = ProjectionUtil.worldSpaceToScreenSpace(targetPos);

        CustomDrawContext context = event.getContext();
        Font font = Fonts.MEDIUM.getFont(8 * markerSize.getCurrent());
        zenith.zov.utility.render.display.base.color.ColorRGBA color = getArrowColor();
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();

        float posX = (float) projected.x;
        float posY = (float) projected.y;

        // Размеры иконки
        float iconSize = 16 * markerSize.getCurrent();

        // Текст
        String gpsText = "GPS";
        String distText = String.format("%.0fm", distance);
        float gpsWidth = font.width(gpsText);
        float distWidth = font.width(distText);
        float maxTextWidth = Math.max(gpsWidth, distWidth);

        // Размеры прямоугольника
        float rectWidth = maxTextWidth + 16 * markerSize.getCurrent();
        float rectHeight = (font.height() * 2 + 6) * markerSize.getCurrent();
        float rectX = posX - rectWidth / 2;
        float rectY = posY + iconSize + 4 * markerSize.getCurrent();

        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().scale(markerSize.getCurrent(), markerSize.getCurrent(), 1f);
        context.getMatrices().translate(-posX, -posY, 0);

        // Рисуем фон для текста
        DrawUtil.drawBlurHud(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 22, BorderRadius.all(2),
                new zenith.zov.utility.render.display.base.color.ColorRGBA(255, 255, 255, 255));
        context.drawRoundedRect(rectX, rectY, rectWidth, rectHeight, BorderRadius.all(2), theme.getForegroundLight());
        DrawUtil.drawRoundedCorner(context.getMatrices(), rectX, rectY, rectWidth, rectHeight, 0.1f, 9, color,
                BorderRadius.all(2));

        // Рисуем иконку стрелки (перевернутую вниз, чуть ниже)
        context.pushMatrix();
        context.getMatrices().translate(posX, posY, 0);
        context.getMatrices().multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(180));
        context.drawTexture(arrowTexture, -iconSize / 2, -iconSize / 2, iconSize, iconSize, markerIconColor.getColor());
        context.popMatrix();

        // Рисуем текст
        context.drawText(font, gpsText, posX - gpsWidth / 2, rectY + 3 * markerSize.getCurrent(), color);
        context.drawText(font, distText, posX - distWidth / 2, rectY + 3 * markerSize.getCurrent() + font.height() + 2,
                color);

        context.popMatrix();
    }
}
Ты бы хотябы EventFTComponent докинул
 
Назад
Сверху Снизу