package sky.client.modules.render; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.resource.language.I18n; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.*; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.text.Text; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.MathHelper; import sky.client.events.Event; import sky.client.events.impl.EventUpdate; import sky.client.events.impl.render.EventRender2D; import sky.client.manager.Manager; import sky.client.manager.dragManager.Dragging; import sky.client.manager.fontManager.FontUtils; import sky.client.modules.Function; import sky.client.modules.FunctionAnnotation; import sky.client.modules.Type; import sky.client.modules.setting.*; import sky.client.util.render.RenderAddon; import sky.client.util.render.RenderUtil; import java.awt.*; import java.util.*; import java.util.List; import java.util.regex.Pattern; @FunctionAnnotation(name = "HUD", desc = "Интерфейс клиента", type = Type.Render) public class HUD extends Function { // Настройки public ModeSetting hudVersion = new ModeSetting("Версия HUD", "Beta", "Beta", "Recode"); public MultiSetting elements = new MultiSetting("Элементы", Arrays.asList("WaterMark", "TargetHUD", "KeyBinds", "StaffList", "PotionHUD", "ItemCoolDownHUD", "Info", "ArmorHUD"), new String[]{"WaterMark", "TargetHUD", "KeyBinds", "StaffList", "PotionHUD", "ItemCoolDownHUD", "Info", "ArmorHUD"}); public SliderSetting customAlpha = new SliderSetting("Прозрачность", 120, 120, 255, 5); public BooleanSetting visibleCrosshair = new BooleanSetting("Показывать TargetHUD при навидении", false); public SliderSetting roundness = new SliderSetting("Закругление", 6, 0, 8, 1); // Dragging объекты public Dragging watermarkDrag; public Dragging targethudDrag; public Dragging keybindsDrag; public Dragging stafflistDrag; public Dragging itemcooldownDrag; public Dragging potionhudDrag; public Dragging coordinateshudDrag; public Dragging armorDrag; // Данные для худа private LivingEntity target = null; private float lastHealth = 0.0f; private final List staffPlayers = new ArrayList<>(); private final Set addedPlayers = new HashSet<>(); // Статические данные private static final Item[] TRACKED_ITEMS = { Items.ENDER_PEARL, Items.CHORUS_FRUIT, Items.FIREWORK_ROCKET, Items.SHIELD, Items.GOLDEN_APPLE, Items.ENCHANTED_GOLDEN_APPLE, Items.TOTEM_OF_UNDYING, Items.SNOWBALL, Items.DRIED_KELP, Items.ENDER_EYE, Items.NETHERITE_SCRAP, Items.EXPERIENCE_BOTTLE, Items.PHANTOM_MEMBRANE }; private static final Map ITEM_NAMES; static { Map tmp = new HashMap<>(); tmp.put(Items.ENDER_PEARL, "Эндер-жемчуг"); tmp.put(Items.CHORUS_FRUIT, "Хорус"); tmp.put(Items.FIREWORK_ROCKET, "Фейерверк"); tmp.put(Items.SHIELD, "Щит"); tmp.put(Items.GOLDEN_APPLE, "Золотое яблоко"); tmp.put(Items.ENCHANTED_GOLDEN_APPLE, "Чарка"); tmp.put(Items.TOTEM_OF_UNDYING, "Тотем"); tmp.put(Items.SNOWBALL, "Снежок"); tmp.put(Items.DRIED_KELP, "Пласт"); tmp.put(Items.ENDER_EYE, "Дезориентация"); tmp.put(Items.NETHERITE_SCRAP, "Трапка"); tmp.put(Items.EXPERIENCE_BOTTLE, "Пузырек опыта"); tmp.put(Items.PHANTOM_MEMBRANE, "Аура"); ITEM_NAMES = Collections.unmodifiableMap(tmp); } private static final Pattern NAME_PATTERN = Pattern.compile("^\\w{3,16}$"); private static final Pattern PREFIX_MATCHES = Pattern.compile(".*(mod|мод|adm|адм|help|хелп|curat|курат|own|овн|dev|supp|сапп|yt|ют|сотруд).*", Pattern.CASE_INSENSITIVE); public HUD() { addSettings(hudVersion, elements, customAlpha, roundness, visibleCrosshair); } @Override public void onEvent(Event event) { if (mc == null || mc.player == null || mc.world == null) return; if (event instanceof EventUpdate) { if (elements.get("StaffList")) { // Используем get() вместо isEnabled() updateStaffPlayers(); } } if (event instanceof EventRender2D) { EventRender2D render2D = (EventRender2D) event; // Инициализация Dragging при первом рендере if (watermarkDrag == null) { initDragging(); } // Выбор версии HUD if (hudVersion.get().equals("Recode")) { // Используем get() для ModeSetting renderRecodeHUD(render2D); } else { renderBetaHUD(render2D); } } } private void initDragging() { // Используем createDrag из Main класса sky.client.Main main = sky.client.Main.getInstance(); watermarkDrag = main.createDrag(this, "WaterMark", 10, 10); targethudDrag = main.createDrag(this, "TargetHUD", 10, 45); keybindsDrag = main.createDrag(this, "KeyBindsHUD", 10, 125); stafflistDrag = main.createDrag(this, "StaffListHUD", 10, 158); itemcooldownDrag = main.createDrag(this, "CoolDownHUD", 10, 195); potionhudDrag = main.createDrag(this, "PotionHUD", 10, 228); coordinateshudDrag = main.createDrag(this, "CoordinatesHUD", 10, 198); armorDrag = main.createDrag(this, "ArmorHUD", 478, 468); } // ==================== BETA VERSION ==================== private void renderBetaHUD(EventRender2D render2D) { MatrixStack matrices = render2D.getMatrixStack(); DrawContext context = render2D.getDrawContext(); if (elements.get("WaterMark")) waterMarkBeta(context, matrices); if (elements.get("TargetHUD")) targetHudBeta(context, matrices); if (elements.get("StaffList")) staffListBeta(context, matrices); if (elements.get("KeyBinds")) keybindHudBeta(context, matrices); if (elements.get("ItemCooldownHUD")) cooldownBeta(context, matrices); if (elements.get("PotionHUD")) potionBeta(context, matrices); if (elements.get("Info")) coordinatesBeta(context, matrices); if (elements.get("ArmorHUD")) armorBeta(context, matrices); } private void waterMarkBeta(DrawContext context, MatrixStack matrices) { float x = watermarkDrag.getX(); float y = watermarkDrag.getY(); String textLogo = "SkyClient"; String nickname = mc.player.getName().getString(); String fpsValue = String.valueOf(sky.client.manager.ClientManager.getFps()); String fpsLabel = "fps"; String pingValue = String.valueOf(getPing()); String pingLabel = "ms"; String separator = " • "; // Расчет ширины float separatorWidth = FontUtils.sf_medium[13].getWidth(separator); float nicknameWidth = FontUtils.sf_medium[13].getWidth(nickname); float fpsValueWidth = FontUtils.sf_medium[13].getWidth(fpsValue); float fpsLabelWidth = FontUtils.sf_medium[13].getWidth(fpsLabel); float pingValueWidth = FontUtils.sf_medium[13].getWidth(pingValue); float pingLabelWidth = FontUtils.sf_medium[13].getWidth(pingLabel); float totalWidth = logoWidth + separatorWidth * 3 + nicknameWidth + fpsValueWidth + fpsLabelWidth + pingValueWidth + pingLabelWidth; float width = totalWidth + 4; float height = 16; // Фон RenderUtil.drawRoundedRect(matrices, x, y, width, height, 1.5f, 0x961E1E1E); float textX = x + 4; float textY = y + 4.0f; // Рендер текста FontUtils.durman[13].drawLeftAligned(matrices, textLogo, textX, textY, -1); textX += logoWidth; FontUtils.sf_medium[13].drawLeftAligned(matrices, separator, textX, textY, new Color(150, 150, 150).getRGB()); textX += separatorWidth; FontUtils.sf_medium[13].drawLeftAligned(matrices, nickname, textX, textY, -1); textX += nicknameWidth; FontUtils.sf_medium[13].drawLeftAligned(matrices, separator, textX, textY, new Color(150, 150, 150).getRGB()); textX += separatorWidth; FontUtils.sf_medium[13].drawLeftAligned(matrices, fpsValue, textX, textY, -1); textX += fpsValueWidth; FontUtils.sf_medium[13].drawLeftAligned(matrices, fpsLabel, textX, textY, new Color(200, 200, 200).getRGB()); textX += fpsLabelWidth; FontUtils.sf_medium[13].drawLeftAligned(matrices, separator, textX, textY, new Color(150, 150, 150).getRGB()); textX += separatorWidth; FontUtils.sf_medium[13].drawLeftAligned(matrices, pingValue, textX, textY, -1); textX += pingValueWidth; FontUtils.sf_medium[13].drawLeftAligned(matrices, pingLabel, textX, textY, new Color(200, 200, 200).getRGB()); watermarkDrag.setWidth(width); watermarkDrag.setHeight(height); } private void targetHudBeta(DrawContext context, MatrixStack matrices) { target = getTarget(); if (target == null) return; float x = targethudDrag.getX(); float y = targethudDrag.getY(); float width = 105; float height = 33; float currentHealth = target.getHealth() + target.getAbsorptionAmount(); float maxHealth = target.getMaxHealth() + target.getAbsorptionAmount(); if (maxHealth <= 0) maxHealth = 20; float healthVal = MathHelper.clamp(currentHealth, 0.0F, maxHealth); lastHealth = lerp(lastHealth, healthVal, 0.15f); float targetHpPerc = MathHelper.clamp(lastHealth / maxHealth, 0f, 1f); // Фон RenderUtil.drawRoundedRect(matrices, x, y, width, height, 1.5f, 0x961E1E1E); // Голова игрока RenderAddon.drawHead(matrices, target, x + 3, y + 2, 28); // Имя String name = target.getName().getString(); FontUtils.sf_bold[13].drawLeftAligned(matrices, name, x + 34, y + 4, -1); // Полоска здоровья float barWidth = width - 38; float barX = x + 33; float barY = y + 20; float barHeight = 8; // Фон полоски RenderUtil.drawRoundedRect(matrices, barX, barY, barWidth, barHeight, 3f, new Color(25, 25, 25).getRGB()); int c1 = Manager.STYLE_MANAGER.getFirstColor(); // Заполненная часть RenderUtil.drawRoundedRect(matrices, barX, barY, barWidth * targetHpPerc, barHeight, 3f, c1); // Текст HP String hpText = String.format("HP: %.1f", currentHealth); FontUtils.sf_medium[11].drawLeftAligned(matrices, hpText, x + 34, barY - 8.5f, -1); targethudDrag.setWidth(width); targethudDrag.setHeight(height); } // Остальные методы сделаем позже private void staffListBeta(DrawContext context, MatrixStack matrices) { // Пока заглушка } private void keybindHudBeta(DrawContext context, MatrixStack matrices) { // Пока заглушка } private void cooldownBeta(DrawContext context, MatrixStack matrices) { // Пока заглушка } private void potionBeta(DrawContext context, MatrixStack matrices) { // Пока заглушка } private void coordinatesBeta(DrawContext context, MatrixStack matrices) { // Пока заглушка } private void armorBeta(DrawContext context, MatrixStack matrices) { // Пока заглушка } // ==================== RECODE VERSION ==================== private void renderRecodeHUD(EventRender2D render2D) { // Пока используем Beta версию renderBetaHUD(render2D); } // ==================== ОБЩИЕ МЕТОДЫ ==================== private void updateStaffPlayers() { // Реализация позже } private LivingEntity getTarget() { LivingEntity target = null; if (Manager.FUNCTION_MANAGER.attackAura.target instanceof LivingEntity) { target = (LivingEntity) Manager.FUNCTION_MANAGER.attackAura.target; } else if (visibleCrosshair.get() && mc.crosshairTarget instanceof EntityHitResult) { Entity aimed = ((EntityHitResult) mc.crosshairTarget).getEntity(); if (aimed instanceof LivingEntity) { target = (LivingEntity) aimed; } } return target; } private int getPing() { if (mc.getNetworkHandler() == null) return 0; PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(mc.player.getUuid()); return entry != null ? entry.getLatency() : 0; } private float lerp(float a, float b, float t) { return a + (b - a) * t; } @Override public void onDisable() { staffPlayers.clear(); addedPlayers.clear(); } // Вспомогательный класс private class StaffPlayer { private final String name; private final Text prefix; private final java.util.UUID uuid; public StaffPlayer(String name, Text prefix, java.util.UUID uuid) { this.name = name; this.prefix = prefix; this.uuid = uuid; } public String getName() { return name; } public Text getPrefix() { return prefix; } public String getStatus() { return "Active"; } } }