Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Визуальная часть Dynamic island | rich 1.21.4

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
3 Май 2025
Сообщения
17
Реакции
0
Выберите загрузчик игры
  1. Fabric
сливаю гптшный островок, первая тема не судите строго
dynamic island:
Expand Collapse Copy
package fun.rich.display.hud;

import com.google.common.base.Suppliers;
import fun.rich.utils.client.managers.api.draggable.AbstractDraggable;
import fun.rich.utils.display.atlasfont.msdf.MsdfFont;
import fun.rich.utils.display.color.ColorAssist;
import fun.rich.utils.display.shape.ShapeProperties;
import fun.rich.utils.display.systemrender.builders.Builder;
import fun.rich.utils.media.MediaUtils;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.ItemStack;
import org.joml.Matrix4f;

import java.awt.*;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.function.Supplier;

public class DynamicIsland extends AbstractDraggable {

    private static final long SHOW_MS = 2200L;

    public enum NotificationType {
        SUCCESS(new Color(0x4AE54A)),
        ERROR  (new Color(0xFF4545)),
        WARNING(new Color(0xFFB830)),
        INFO   (new Color(0x4AADFF)),
        DEFAULT(new Color(0xA855F7));
        public final Color color;
        NotificationType(Color c) { this.color = c; }
    }

    private record Notif(String text, Color color) {}

    private static volatile Notif     active    = null;
    private static volatile long      activeEnd = 0L;
    private static final Queue<Notif> queue     = new ArrayDeque<>();

    public static void addNotification(String text, NotificationType type) {
        Notif n = new Notif(text, type.color);
        if (active == null || System.currentTimeMillis() >= activeEnd) {
            active    = n;
            activeEnd = System.currentTimeMillis() + SHOW_MS;
        } else {
            queue.offer(n);
        }
    }

    public static void notifyModuleToggle(String name, boolean enabled) {
        addNotification(name + (enabled ? " включен" : " выключен"),
                enabled ? NotificationType.SUCCESS : NotificationType.ERROR);
    }

    public static void strengthNotification() {
        if (mc.player == null) return;
        EquipmentSlot[] slots = {
            EquipmentSlot.HEAD, EquipmentSlot.CHEST,
            EquipmentSlot.LEGS, EquipmentSlot.FEET
        };
        String[] names = {"Шлем", "Нагрудник", "Поножи", "Ботинки"};
        for (int i = 0; i < slots.length; i++) {
            ItemStack s = mc.player.getEquippedStack(slots[i]);
            if (s.isEmpty() || !s.isDamageable()) continue;
            float pct = (float)(s.getMaxDamage() - s.getDamage()) / s.getMaxDamage();
            if (pct <= 0.1f && pct > 0f)
                addNotification(names[i] + " имеет низкую прочность!", NotificationType.WARNING);
        }
    }

    private static final Supplier<MsdfFont> F_MEDIUM  =
            Suppliers.memoize(() -> MsdfFont.builder().atlas("medium").data("medium").build());
    private static final Supplier<MsdfFont> F_REGULAR =
            Suppliers.memoize(() -> MsdfFont.builder().atlas("regular").data("regular").build());
    private static final Supplier<MsdfFont> F_ICON    =
            Suppliers.memoize(() -> MsdfFont.builder().atlas("clienticon1").data("clienticon1").build());

    private static final Color BG      = new Color(18, 18, 22, 220);
    private static final Color BG_DARK = new Color(12, 12, 16, 220);

    private float pillW = 80f;
    private static final float PILL_H = 18f;

    private final float[] waveH   = {3f, 7f, 4f, 8f};
    private final float[] waveDir = {1f, -1f, 1f, -1f};
    private final float[] waveSpd = {0.18f, 0.22f, 0.15f, 0.20f};

    public DynamicIsland() {
        super("Watermark", 10, 10, 80, 18, false);
    }

    @Override
    public void tick() {
        if (active != null && System.currentTimeMillis() >= activeEnd) {
            Notif next = queue.poll();
            active    = next;
            activeEnd = next != null ? System.currentTimeMillis() + SHOW_MS : 0L;
        }
        for (int i = 0; i < 4; i++) {
            waveH[i] += waveDir[i] * waveSpd[i];
            if (waveH[i] >= 9f) { waveH[i] = 9f; waveDir[i] = -1f; waveSpd[i] = 0.12f + (float)(Math.random() * 0.18f); }
            if (waveH[i] <= 2f) { waveH[i] = 2f; waveDir[i] =  1f; waveSpd[i] = 0.12f + (float)(Math.random() * 0.18f); }
        }
    }

    @Override
    public void drawDraggable(DrawContext context) {
        MatrixStack ms  = context.getMatrices();
        Matrix4f    mat = ms.peek().getPositionMatrix();
        int         sw  = window.getScaledWidth();

        boolean hasNotif = active != null && System.currentTimeMillis() < activeEnd;
        MediaUtils.MediaInfo media = MediaUtils.getCurrentMedia();
        boolean hasMedia = !hasNotif && media != null && !media.title.isEmpty();

        String time  = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm"));
        float  timeW = F_MEDIUM.get().getWidth(time, 8.5f);

        float targetW;
        if (hasNotif) {
            float tw = F_REGULAR.get().getWidth(active.text(), 8.5f);
            targetW = 8f + 7f + 5f + tw + 8f;
        } else if (hasMedia) {
            String t = trimTitle(media.title);
            float tw = F_REGULAR.get().getWidth(t, 8.5f);
            targetW = 8f + tw + 6f + waveGroupW() + 8f;
        } else {
            float nameW = F_REGULAR.get().getWidth(getDisplayName(), 8.5f);
            targetW = 8f + 10f + 1f + nameW + 8f;
        }

        pillW += (targetW - pillW) * 0.18f;

        float pingGroupW = 4 * 3.3f + 3f;
        float totalW     = timeW + 6f + pillW + 6f + pingGroupW;
        float startX     = sw / 2f - totalW / 2f;
        float pillX      = startX + timeW + 6f;
        float pillY      = 5f;
        float midY       = pillY + PILL_H / 2f;
        float ty         = midY - 8.5f / 2f - 0.5f;

        Builder.text().font(F_MEDIUM.get()).text(time).size(8.5f)
                .thickness(0.04f).color(ColorAssist.getText()).build()
                .render(mat, startX, ty);

        blur.render(ShapeProperties.create(ms, pillX, pillY, pillW, PILL_H)
                .round(PILL_H / 2f).quality(14).color(BG.getRGB()).build());
        rectangle.render(ShapeProperties.create(ms, pillX, pillY, pillW, PILL_H)
                .round(PILL_H / 2f).thickness(0.15f)
                .outlineColor(new Color(255, 255, 255, 18).getRGB())
                .color(BG.getRGB(), BG_DARK.getRGB(), BG_DARK.getRGB(), BG.getRGB()).build());

        float cx = pillX + 8f;

        if (hasNotif) {
            float dotR = 3.5f;
            rectangle.render(ShapeProperties.create(ms, cx, midY - dotR, dotR * 2f, dotR * 2f)
                    .round(dotR).color(active.color().getRGB()).build());
            cx += dotR * 2f + 5f;
            Builder.text().font(F_REGULAR.get()).text(active.text()).size(8.5f)
                    .thickness(0.04f).color(ColorAssist.getText()).build()
                    .render(mat, cx, ty);
        } else if (hasMedia) {
            String t = trimTitle(media.title);
            Builder.text().font(F_REGULAR.get()).text(t).size(8.5f)
                    .thickness(0.04f).color(ColorAssist.getText()).build()
                    .render(mat, cx, ty);
            cx += F_REGULAR.get().getWidth(t, 8.5f) + 6f;
            renderWaveBars(ms, cx, midY);
        } else {
            renderPixelHeart(ms, cx, midY - 4.5f, ColorAssist.getClientColor());
            cx += 11f;
            Builder.text().font(F_REGULAR.get()).text(getDisplayName()).size(8.5f)
                    .thickness(0.04f).color(ColorAssist.getText()).build()
                    .render(mat, cx, ty - 1f);
        }

        float barsX = pillX + pillW + 6f;
        float barsY = midY - 10f / 2f;
        renderPing(ms, barsX, barsY);

        setX((int) pillX); setY((int) pillY);
        setWidth((int) pillW); setHeight((int) PILL_H);
    }

    private void renderWaveBars(MatrixStack ms, float x, float midY) {
        int color = ColorAssist.getText(0.9f);
        for (int i = 0; i < 4; i++) {
            float bh = waveH[i];
            rectangle.render(ShapeProperties.create(ms, x + i * 4f, midY - bh / 2f, 2.5f, bh)
                    .round(1f).color(color).build());
        }
    }

    private float waveGroupW() { return 4 * 2.5f + 3 * 1.5f; }

    private void renderPing(MatrixStack ms, float x, float y) {
        int ping = getPlayerPing();
        int lit  = ping <= 50 ? 4 : ping <= 80 ? 3 : ping <= 120 ? 2 : ping <= 180 ? 1 : 0;
        int[] maxH = {4, 6, 8, 10};
        long  t    = System.currentTimeMillis();
        for (int i = 0; i < 4; i++) {
            float breath = (float)(Math.sin(t / 600.0 + i * 0.7) * 0.5 + 0.5);
            float bh = i < lit ? maxH[i] * (0.6f + 0.4f * breath) : maxH[i] * (0.25f + 0.1f * breath);
            int col = i < lit ? ColorAssist.getText(0.85f) : ColorAssist.getText(0.18f);
            rectangle.render(ShapeProperties.create(ms, x + i * 3.3f, y + (10 - bh), 2.8f, bh)
                    .round(1f).color(col).build());
        }
    }

    private static final int[][] HEART = {
        {0,1,1,0,0,0,1,1,0},
        {1,1,1,1,0,1,1,1,1},
        {1,1,1,1,1,1,1,1,1},
        {1,1,1,1,1,1,1,1,1},
        {0,1,1,1,1,1,1,1,0},
        {0,0,1,1,1,1,1,0,0},
        {0,0,0,1,1,1,0,0,0},
        {0,0,0,0,1,0,0,0,0},
    };

    private void renderPixelHeart(MatrixStack ms, float x, float y, int color) {
        float px = 1.1f;
        for (int row = 0; row < HEART.length; row++)
            for (int col = 0; col < HEART[row].length; col++)
                if (HEART[row][col] == 1)
                    rectangle.render(ShapeProperties.create(ms, x + col * px, y + row * px, px, px)
                            .round(0f).color(color).build());
    }

    private String trimTitle(String s) { return s.length() > 22 ? s.substring(0, 20) + "…" : s; }
    private String getDisplayName() { return "Paradox"; }

    private int getPlayerPing() {
        if (mc.player == null || mc.getNetworkHandler() == null) return 0;
        PlayerListEntry e = mc.getNetworkHandler().getPlayerListEntry(mc.player.getUuid());
        return e != null ? e.getLatency() : 0;
    }
}
mediautils:
Expand Collapse Copy
package fun.rich.utils.media;

import by.bonenaut7.mediatransport4j.api.MediaSession;
import by.bonenaut7.mediatransport4j.api.MediaTransport;
import com.google.common.io.BaseEncoding;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture;
import net.minecraft.util.Identifier;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.Map;

public class MediaUtils {

    private static boolean initialized = false;
    private static final ScheduledExecutorService EXECUTOR =
            Executors.newSingleThreadScheduledExecutor(r -> {
                Thread t = new Thread(r, "MediaUtils");
                t.setDaemon(true);
                return t;
            });

    private static volatile MediaInfo mediaInfo = null;
    private static volatile MediaSession activeSession = null;
    public static volatile Color lastAlbumColor = Color.WHITE;

    private static final Map<String, Identifier> textureCache = new ConcurrentHashMap<>();
    private static String previousHash = "";

    public static class MediaInfo {
        public final String title;
        public final String artist;
        public final String textureHash;
        public final boolean isPlaying;
        public final long   positionMs;
        public final long   durationMs;
        public final long   pollTimeMs;

        public MediaInfo(String title, String artist, String textureHash,
                         boolean isPlaying, long positionMs, long durationMs, long pollTimeMs) {
            this.title       = title;
            this.artist      = artist;
            this.textureHash = textureHash;
            this.isPlaying   = isPlaying;
            this.positionMs  = positionMs;
            this.durationMs  = durationMs;
            this.pollTimeMs  = pollTimeMs;
        }

        public long estimatedPositionMs() {
            if (!isPlaying) return positionMs;
            long elapsed = System.currentTimeMillis() - pollTimeMs;
            return Math.min(positionMs + elapsed, durationMs > 0 ? durationMs : Long.MAX_VALUE);
        }

        public Identifier getTexture() {
            return textureCache.get(textureHash);
        }
    }

    public static void init() {
        if (initialized) return;
        MediaTransport.init();
        initialized = true;
        EXECUTOR.scheduleAtFixedRate(() -> {
            try {
                List<MediaSession> sessions = MediaTransport.getMediaSessions();
                if (sessions != null && !sessions.isEmpty()) {
                    MediaSession session = sessions.get(0);
                    activeSession = session;

                    String hash = "";
                    if (session.hasThumbnail()) {
                        ByteBuffer buf = session.getThumbnail();
                        hash = hashBuffer(buf);
                        if (!hash.equals(previousHash)) {
                            Identifier old = textureCache.remove(previousHash);
                            if (old != null) {
                                MinecraftClient.getInstance().execute(() ->
                                    MinecraftClient.getInstance().getTextureManager().destroyTexture(old));
                            }
                            final String finalHash = hash;
                            Identifier id = registerTexture(buf, finalHash);
                            if (id != null) textureCache.put(hash, id);
                            previousHash = hash;
                        }
                    }

                    boolean playing  = session.isPlaying();
                    long    pos      = session.getPosition();
                    long    dur      = session.getDuration();

                    mediaInfo = new MediaInfo(
                            session.getTitle(), session.getArtist(), hash,
                            playing, pos, dur, System.currentTimeMillis()
                    );
                } else {
                    activeSession = null;
                    clearCache();
                    mediaInfo = null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 0, 100, TimeUnit.MILLISECONDS);
    }

    public static MediaInfo getCurrentMedia() {
        if (!initialized) init();
        return mediaInfo;
    }

    public static void playPause() {
        MediaSession s = activeSession;
        if (s != null) EXECUTOR.submit(() -> { try { s.togglePlay(); } catch (Exception ignored) {} });
    }

    public static void next() {
        MediaSession s = activeSession;
        if (s != null) EXECUTOR.submit(() -> { try { s.switchToNext(); } catch (Exception ignored) {} });
    }

    public static void previous() {
        MediaSession s = activeSession;
        if (s != null) EXECUTOR.submit(() -> { try { s.switchToPrevious(); } catch (Exception ignored) {} });
    }

    private static Identifier registerTexture(ByteBuffer buffer, String hash) {
        try {
            BufferedImage img = ImageIO.read(new ByteArrayInputStream(buffer.array()));
            if (img == null) return null;

            lastAlbumColor = averageColor(img);

            BufferedImage argb = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = argb.createGraphics();
            g.drawImage(img, 0, 0, null);
            g.dispose();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(argb, "png", baos);
            byte[] pngBytes = baos.toByteArray();

            Identifier id = Identifier.of("rich", "media/" + hash);
            MinecraftClient.getInstance().execute(() -> {
                try {
                    NativeImage ni = NativeImage.read(new ByteArrayInputStream(pngBytes));
                    MinecraftClient.getInstance().getTextureManager()
                            .registerTexture(id, new NativeImageBackedTexture(ni));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            return id;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static void clearCache() {
        textureCache.forEach((k, id) ->
            MinecraftClient.getInstance().execute(() ->
                MinecraftClient.getInstance().getTextureManager().destroyTexture(id)));
        textureCache.clear();
        previousHash = "";
    }

    private static String hashBuffer(ByteBuffer buffer) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(buffer.array());
            return BaseEncoding.base16().lowerCase().encode(md.digest());
        } catch (Exception e) {
            return "";
        }
    }

    private static Color averageColor(BufferedImage img) {
        long r = 0, g = 0, b = 0;
        int count = 0, step = 5;
        for (int x = 0; x < img.getWidth(); x += step)
            for (int y = 0; y < img.getHeight(); y += step) {
                int rgb = img.getRGB(x, y);
                r += (rgb >> 16) & 0xFF;
                g += (rgb >> 8)  & 0xFF;
                b +=  rgb        & 0xFF;
                count++;
            }
        return count == 0 ? Color.WHITE
                : new Color((int)(r/count), (int)(g/count), (int)(b/count));
    }
}


Пожалуйста, авторизуйтесь для просмотра ссылки.
еще либку mediatransport4j-1.0.3 скачаете
 
по моему или это говно постил уже каждой второй и че оно кривое такое
но для первой темы простительно
на рич не было помоему
Смысл от этой ватермарки? Вообще какой еблан придумал пиздить островок с айфона в нищий чит для маинкрафта
так ето крута модно молодежно , да и вообще мне просто больше островок нравиться а не ватермарка
 
сливаю гптшный островок, первая тема не судите строго
dynamic island:
Expand Collapse Copy
package fun.rich.display.hud;

import com.google.common.base.Suppliers;
import fun.rich.utils.client.managers.api.draggable.AbstractDraggable;
import fun.rich.utils.display.atlasfont.msdf.MsdfFont;
import fun.rich.utils.display.color.ColorAssist;
import fun.rich.utils.display.shape.ShapeProperties;
import fun.rich.utils.display.systemrender.builders.Builder;
import fun.rich.utils.media.MediaUtils;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.ItemStack;
import org.joml.Matrix4f;

import java.awt.*;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.function.Supplier;

public class DynamicIsland extends AbstractDraggable {

    private static final long SHOW_MS = 2200L;

    public enum NotificationType {
        SUCCESS(new Color(0x4AE54A)),
        ERROR  (new Color(0xFF4545)),
        WARNING(new Color(0xFFB830)),
        INFO   (new Color(0x4AADFF)),
        DEFAULT(new Color(0xA855F7));
        public final Color color;
        NotificationType(Color c) { this.color = c; }
    }

    private record Notif(String text, Color color) {}

    private static volatile Notif     active    = null;
    private static volatile long      activeEnd = 0L;
    private static final Queue<Notif> queue     = new ArrayDeque<>();

    public static void addNotification(String text, NotificationType type) {
        Notif n = new Notif(text, type.color);
        if (active == null || System.currentTimeMillis() >= activeEnd) {
            active    = n;
            activeEnd = System.currentTimeMillis() + SHOW_MS;
        } else {
            queue.offer(n);
        }
    }

    public static void notifyModuleToggle(String name, boolean enabled) {
        addNotification(name + (enabled ? " включен" : " выключен"),
                enabled ? NotificationType.SUCCESS : NotificationType.ERROR);
    }

    public static void strengthNotification() {
        if (mc.player == null) return;
        EquipmentSlot[] slots = {
            EquipmentSlot.HEAD, EquipmentSlot.CHEST,
            EquipmentSlot.LEGS, EquipmentSlot.FEET
        };
        String[] names = {"Шлем", "Нагрудник", "Поножи", "Ботинки"};
        for (int i = 0; i < slots.length; i++) {
            ItemStack s = mc.player.getEquippedStack(slots[i]);
            if (s.isEmpty() || !s.isDamageable()) continue;
            float pct = (float)(s.getMaxDamage() - s.getDamage()) / s.getMaxDamage();
            if (pct <= 0.1f && pct > 0f)
                addNotification(names[i] + " имеет низкую прочность!", NotificationType.WARNING);
        }
    }

    private static final Supplier<MsdfFont> F_MEDIUM  =
            Suppliers.memoize(() -> MsdfFont.builder().atlas("medium").data("medium").build());
    private static final Supplier<MsdfFont> F_REGULAR =
            Suppliers.memoize(() -> MsdfFont.builder().atlas("regular").data("regular").build());
    private static final Supplier<MsdfFont> F_ICON    =
            Suppliers.memoize(() -> MsdfFont.builder().atlas("clienticon1").data("clienticon1").build());

    private static final Color BG      = new Color(18, 18, 22, 220);
    private static final Color BG_DARK = new Color(12, 12, 16, 220);

    private float pillW = 80f;
    private static final float PILL_H = 18f;

    private final float[] waveH   = {3f, 7f, 4f, 8f};
    private final float[] waveDir = {1f, -1f, 1f, -1f};
    private final float[] waveSpd = {0.18f, 0.22f, 0.15f, 0.20f};

    public DynamicIsland() {
        super("Watermark", 10, 10, 80, 18, false);
    }

    @Override
    public void tick() {
        if (active != null && System.currentTimeMillis() >= activeEnd) {
            Notif next = queue.poll();
            active    = next;
            activeEnd = next != null ? System.currentTimeMillis() + SHOW_MS : 0L;
        }
        for (int i = 0; i < 4; i++) {
            waveH[i] += waveDir[i] * waveSpd[i];
            if (waveH[i] >= 9f) { waveH[i] = 9f; waveDir[i] = -1f; waveSpd[i] = 0.12f + (float)(Math.random() * 0.18f); }
            if (waveH[i] <= 2f) { waveH[i] = 2f; waveDir[i] =  1f; waveSpd[i] = 0.12f + (float)(Math.random() * 0.18f); }
        }
    }

    @Override
    public void drawDraggable(DrawContext context) {
        MatrixStack ms  = context.getMatrices();
        Matrix4f    mat = ms.peek().getPositionMatrix();
        int         sw  = window.getScaledWidth();

        boolean hasNotif = active != null && System.currentTimeMillis() < activeEnd;
        MediaUtils.MediaInfo media = MediaUtils.getCurrentMedia();
        boolean hasMedia = !hasNotif && media != null && !media.title.isEmpty();

        String time  = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm"));
        float  timeW = F_MEDIUM.get().getWidth(time, 8.5f);

        float targetW;
        if (hasNotif) {
            float tw = F_REGULAR.get().getWidth(active.text(), 8.5f);
            targetW = 8f + 7f + 5f + tw + 8f;
        } else if (hasMedia) {
            String t = trimTitle(media.title);
            float tw = F_REGULAR.get().getWidth(t, 8.5f);
            targetW = 8f + tw + 6f + waveGroupW() + 8f;
        } else {
            float nameW = F_REGULAR.get().getWidth(getDisplayName(), 8.5f);
            targetW = 8f + 10f + 1f + nameW + 8f;
        }

        pillW += (targetW - pillW) * 0.18f;

        float pingGroupW = 4 * 3.3f + 3f;
        float totalW     = timeW + 6f + pillW + 6f + pingGroupW;
        float startX     = sw / 2f - totalW / 2f;
        float pillX      = startX + timeW + 6f;
        float pillY      = 5f;
        float midY       = pillY + PILL_H / 2f;
        float ty         = midY - 8.5f / 2f - 0.5f;

        Builder.text().font(F_MEDIUM.get()).text(time).size(8.5f)
                .thickness(0.04f).color(ColorAssist.getText()).build()
                .render(mat, startX, ty);

        blur.render(ShapeProperties.create(ms, pillX, pillY, pillW, PILL_H)
                .round(PILL_H / 2f).quality(14).color(BG.getRGB()).build());
        rectangle.render(ShapeProperties.create(ms, pillX, pillY, pillW, PILL_H)
                .round(PILL_H / 2f).thickness(0.15f)
                .outlineColor(new Color(255, 255, 255, 18).getRGB())
                .color(BG.getRGB(), BG_DARK.getRGB(), BG_DARK.getRGB(), BG.getRGB()).build());

        float cx = pillX + 8f;

        if (hasNotif) {
            float dotR = 3.5f;
            rectangle.render(ShapeProperties.create(ms, cx, midY - dotR, dotR * 2f, dotR * 2f)
                    .round(dotR).color(active.color().getRGB()).build());
            cx += dotR * 2f + 5f;
            Builder.text().font(F_REGULAR.get()).text(active.text()).size(8.5f)
                    .thickness(0.04f).color(ColorAssist.getText()).build()
                    .render(mat, cx, ty);
        } else if (hasMedia) {
            String t = trimTitle(media.title);
            Builder.text().font(F_REGULAR.get()).text(t).size(8.5f)
                    .thickness(0.04f).color(ColorAssist.getText()).build()
                    .render(mat, cx, ty);
            cx += F_REGULAR.get().getWidth(t, 8.5f) + 6f;
            renderWaveBars(ms, cx, midY);
        } else {
            renderPixelHeart(ms, cx, midY - 4.5f, ColorAssist.getClientColor());
            cx += 11f;
            Builder.text().font(F_REGULAR.get()).text(getDisplayName()).size(8.5f)
                    .thickness(0.04f).color(ColorAssist.getText()).build()
                    .render(mat, cx, ty - 1f);
        }

        float barsX = pillX + pillW + 6f;
        float barsY = midY - 10f / 2f;
        renderPing(ms, barsX, barsY);

        setX((int) pillX); setY((int) pillY);
        setWidth((int) pillW); setHeight((int) PILL_H);
    }

    private void renderWaveBars(MatrixStack ms, float x, float midY) {
        int color = ColorAssist.getText(0.9f);
        for (int i = 0; i < 4; i++) {
            float bh = waveH[i];
            rectangle.render(ShapeProperties.create(ms, x + i * 4f, midY - bh / 2f, 2.5f, bh)
                    .round(1f).color(color).build());
        }
    }

    private float waveGroupW() { return 4 * 2.5f + 3 * 1.5f; }

    private void renderPing(MatrixStack ms, float x, float y) {
        int ping = getPlayerPing();
        int lit  = ping <= 50 ? 4 : ping <= 80 ? 3 : ping <= 120 ? 2 : ping <= 180 ? 1 : 0;
        int[] maxH = {4, 6, 8, 10};
        long  t    = System.currentTimeMillis();
        for (int i = 0; i < 4; i++) {
            float breath = (float)(Math.sin(t / 600.0 + i * 0.7) * 0.5 + 0.5);
            float bh = i < lit ? maxH[i] * (0.6f + 0.4f * breath) : maxH[i] * (0.25f + 0.1f * breath);
            int col = i < lit ? ColorAssist.getText(0.85f) : ColorAssist.getText(0.18f);
            rectangle.render(ShapeProperties.create(ms, x + i * 3.3f, y + (10 - bh), 2.8f, bh)
                    .round(1f).color(col).build());
        }
    }

    private static final int[][] HEART = {
        {0,1,1,0,0,0,1,1,0},
        {1,1,1,1,0,1,1,1,1},
        {1,1,1,1,1,1,1,1,1},
        {1,1,1,1,1,1,1,1,1},
        {0,1,1,1,1,1,1,1,0},
        {0,0,1,1,1,1,1,0,0},
        {0,0,0,1,1,1,0,0,0},
        {0,0,0,0,1,0,0,0,0},
    };

    private void renderPixelHeart(MatrixStack ms, float x, float y, int color) {
        float px = 1.1f;
        for (int row = 0; row < HEART.length; row++)
            for (int col = 0; col < HEART[row].length; col++)
                if (HEART[row][col] == 1)
                    rectangle.render(ShapeProperties.create(ms, x + col * px, y + row * px, px, px)
                            .round(0f).color(color).build());
    }

    private String trimTitle(String s) { return s.length() > 22 ? s.substring(0, 20) + "…" : s; }
    private String getDisplayName() { return "Paradox"; }

    private int getPlayerPing() {
        if (mc.player == null || mc.getNetworkHandler() == null) return 0;
        PlayerListEntry e = mc.getNetworkHandler().getPlayerListEntry(mc.player.getUuid());
        return e != null ? e.getLatency() : 0;
    }
}
mediautils:
Expand Collapse Copy
package fun.rich.utils.media;

import by.bonenaut7.mediatransport4j.api.MediaSession;
import by.bonenaut7.mediatransport4j.api.MediaTransport;
import com.google.common.io.BaseEncoding;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture;
import net.minecraft.util.Identifier;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.Map;

public class MediaUtils {

    private static boolean initialized = false;
    private static final ScheduledExecutorService EXECUTOR =
            Executors.newSingleThreadScheduledExecutor(r -> {
                Thread t = new Thread(r, "MediaUtils");
                t.setDaemon(true);
                return t;
            });

    private static volatile MediaInfo mediaInfo = null;
    private static volatile MediaSession activeSession = null;
    public static volatile Color lastAlbumColor = Color.WHITE;

    private static final Map<String, Identifier> textureCache = new ConcurrentHashMap<>();
    private static String previousHash = "";

    public static class MediaInfo {
        public final String title;
        public final String artist;
        public final String textureHash;
        public final boolean isPlaying;
        public final long   positionMs;
        public final long   durationMs;
        public final long   pollTimeMs;

        public MediaInfo(String title, String artist, String textureHash,
                         boolean isPlaying, long positionMs, long durationMs, long pollTimeMs) {
            this.title       = title;
            this.artist      = artist;
            this.textureHash = textureHash;
            this.isPlaying   = isPlaying;
            this.positionMs  = positionMs;
            this.durationMs  = durationMs;
            this.pollTimeMs  = pollTimeMs;
        }

        public long estimatedPositionMs() {
            if (!isPlaying) return positionMs;
            long elapsed = System.currentTimeMillis() - pollTimeMs;
            return Math.min(positionMs + elapsed, durationMs > 0 ? durationMs : Long.MAX_VALUE);
        }

        public Identifier getTexture() {
            return textureCache.get(textureHash);
        }
    }

    public static void init() {
        if (initialized) return;
        MediaTransport.init();
        initialized = true;
        EXECUTOR.scheduleAtFixedRate(() -> {
            try {
                List<MediaSession> sessions = MediaTransport.getMediaSessions();
                if (sessions != null && !sessions.isEmpty()) {
                    MediaSession session = sessions.get(0);
                    activeSession = session;

                    String hash = "";
                    if (session.hasThumbnail()) {
                        ByteBuffer buf = session.getThumbnail();
                        hash = hashBuffer(buf);
                        if (!hash.equals(previousHash)) {
                            Identifier old = textureCache.remove(previousHash);
                            if (old != null) {
                                MinecraftClient.getInstance().execute(() ->
                                    MinecraftClient.getInstance().getTextureManager().destroyTexture(old));
                            }
                            final String finalHash = hash;
                            Identifier id = registerTexture(buf, finalHash);
                            if (id != null) textureCache.put(hash, id);
                            previousHash = hash;
                        }
                    }

                    boolean playing  = session.isPlaying();
                    long    pos      = session.getPosition();
                    long    dur      = session.getDuration();

                    mediaInfo = new MediaInfo(
                            session.getTitle(), session.getArtist(), hash,
                            playing, pos, dur, System.currentTimeMillis()
                    );
                } else {
                    activeSession = null;
                    clearCache();
                    mediaInfo = null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 0, 100, TimeUnit.MILLISECONDS);
    }

    public static MediaInfo getCurrentMedia() {
        if (!initialized) init();
        return mediaInfo;
    }

    public static void playPause() {
        MediaSession s = activeSession;
        if (s != null) EXECUTOR.submit(() -> { try { s.togglePlay(); } catch (Exception ignored) {} });
    }

    public static void next() {
        MediaSession s = activeSession;
        if (s != null) EXECUTOR.submit(() -> { try { s.switchToNext(); } catch (Exception ignored) {} });
    }

    public static void previous() {
        MediaSession s = activeSession;
        if (s != null) EXECUTOR.submit(() -> { try { s.switchToPrevious(); } catch (Exception ignored) {} });
    }

    private static Identifier registerTexture(ByteBuffer buffer, String hash) {
        try {
            BufferedImage img = ImageIO.read(new ByteArrayInputStream(buffer.array()));
            if (img == null) return null;

            lastAlbumColor = averageColor(img);

            BufferedImage argb = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = argb.createGraphics();
            g.drawImage(img, 0, 0, null);
            g.dispose();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(argb, "png", baos);
            byte[] pngBytes = baos.toByteArray();

            Identifier id = Identifier.of("rich", "media/" + hash);
            MinecraftClient.getInstance().execute(() -> {
                try {
                    NativeImage ni = NativeImage.read(new ByteArrayInputStream(pngBytes));
                    MinecraftClient.getInstance().getTextureManager()
                            .registerTexture(id, new NativeImageBackedTexture(ni));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            return id;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static void clearCache() {
        textureCache.forEach((k, id) ->
            MinecraftClient.getInstance().execute(() ->
                MinecraftClient.getInstance().getTextureManager().destroyTexture(id)));
        textureCache.clear();
        previousHash = "";
    }

    private static String hashBuffer(ByteBuffer buffer) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(buffer.array());
            return BaseEncoding.base16().lowerCase().encode(md.digest());
        } catch (Exception e) {
            return "";
        }
    }

    private static Color averageColor(BufferedImage img) {
        long r = 0, g = 0, b = 0;
        int count = 0, step = 5;
        for (int x = 0; x < img.getWidth(); x += step)
            for (int y = 0; y < img.getHeight(); y += step) {
                int rgb = img.getRGB(x, y);
                r += (rgb >> 16) & 0xFF;
                g += (rgb >> 8)  & 0xFF;
                b +=  rgb        & 0xFF;
                count++;
            }
        return count == 0 ? Color.WHITE
                : new Color((int)(r/count), (int)(g/count), (int)(b/count));
    }
}


Пожалуйста, авторизуйтесь для просмотра ссылки.
еще либку mediatransport4j-1.0.3 скачаете
кривая залупа
которую сделал уже каждый и без особой разницы в дизайне
 
Назад
Сверху Снизу