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

Гайд Как сделать плашку с музыкой и кнопками в худе MCP 1.16.5

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
9 Июн 2024
Сообщения
119
Реакции
0
Гайд поможет реализовать показ текущий воспроизводимый трек в худе клиента. Это может включать название песни, исполнителя, обложку альбома, прогресс воспроизведения и элементы управления, такие как пауза, воспроизведение и переключение треков. Для реализации используется библиотека, позволяющая получать информацию о системных медиа сессиях.​

Библиотека
Для получения информации о треках используется библиотека
Пожалуйста, авторизуйтесь для просмотра ссылки.
. Она предоставляет список активных медиасессий и позволяет управлять воспроизведением: пауза, продолжение, переключение треков. (для корректной работы ещё потребуется либка
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

Создание модуля
Создаём модуль, который будет хранить текущий трек, медиасессию и текстуру обложки. Также понадобится отдельный поток для асинхронного обновления, чтобы не блокировать игровой поток.

поля и поток:
Expand Collapse Copy
private volatile MediaInfo currentTrack;
private volatile IMediaSession currentSession;
private long lastMediaUpdate;

private final ExecutorService mediaExecutor =
        Executors.newSingleThreadExecutor(r -> {
            Thread t = new Thread(r, "media-thread");
            t.setDaemon(true);
            return t;
        });


Обновление информации о треке
Информацию о музыке удобно обновлять в евенттике. Делать это каждый тик не нужно - достаточно раз в 1-2 секунды.

обновление:
Expand Collapse Copy
@EventHandler
public void onTick(TickEvent e) {
    long now = System.currentTimeMillis();
    if (now - lastMediaUpdate < 1500) return;
    lastMediaUpdate = now;
    updateMediaAsync();
}

Асинхронное получение медиасессии:
получение сессии:
Expand Collapse Copy
private void updateMediaAsync() {
    mediaExecutor.execute(() -> {
        List<IMediaSession> sessions = MediaPlayerInfo.Instance.getMediaSessions();

        if (sessions == null || sessions.isEmpty()) {
            currentTrack = null;
            currentSession = null;
            return;
        }

        MediaInfo found = null;
        IMediaSession foundSession = null;

        for (IMediaSession session : sessions) {
            if (session == null) continue;

            MediaInfo media;
            try {
                media = session.getMedia();
            } catch (Exception e) {
                continue;
            }

            if (media == null) continue;

            if (media.getPlaying()) {
                found = media;
                foundSession = session;
                break;
            }

            if (found == null) {
                found = media;
                foundSession = session;
            }
        }

        currentTrack = found;
        currentSession = foundSession;
    });
}


Загрузка обложки трека
Если плеер отдаёт обложку, её можно превратить в текстуру Minecraft.

отрисовка обложки трека:
Expand Collapse Copy
private ResourceLocation artworkTexture;

private void applyArtwork(byte[] artBytes) {
    try {
        NativeImage img = NativeImage.read(new ByteArrayInputStream(artBytes));
        DynamicTexture texture = new DynamicTexture(img);
        artworkTexture = Minecraft.getInstance()
                .getTextureManager()
                .getDynamicTextureLocation("media_art", texture);
    } catch (Exception ignored) {}
}


Отрисовка в HUD
Рендер худа у меня выполняется в событии HudRenderEvent, там и буду рисовать панельку. Здесь выводится обложка, название трека, исполнитель и прогресс. На примере всё будет прям в методе события, но желательно вынести в отдельный метод.
(методы и аргументация методов будет отличатся, база своя)
код отрисовки:
Expand Collapse Copy
@EventHandler
public void onHudRender(HudRenderEvent e) {
    if (currentTrack == null) return;

    Minecraft mc = Minecraft.getInstance();

    String title = currentTrack.getTitle().isEmpty()
            ? "Unknown"
            : currentTrack.getTitle();

    String artist = currentTrack.getArtist().isEmpty()
            ? "Unknown"
            : currentTrack.getArtist();

    long position = currentTrack.getPosition();
    long duration = currentTrack.getDuration();
    float progress = duration > 0 ? (float) position / duration : 0f;

    float x = mc.getMainWindow().getScaledWidth() / 2f - 60;
    float y = 20;

    RenderUtils.drawRoundedRect(x, y, 120, 40, 6f, 0xAA000000, 0xAA000000);

    if (artworkTexture != null) {
        RenderUtils.drawImage(artworkTexture, x + 4, y + 4, 32, 32, 0xFFFFFFFF);
    }

    FontRenderer font = FontManager.getInstance().getDefaultFont();
    font.drawString(title, x + 40, y + 8, 0xFFFFFFFF);
    font.drawString(artist, x + 40, y + 20, 0xFFAAAAAA);

    RenderUtils.drawRoundedRect(
            x + 4,
            y + 36,
            112 * progress,
            2,
            1,
            0xFFFFFFFF,
            0xFFFFFFFF
    );
}


Кнопки управления
Можно добавить управление воспроизведением: предыдущий трек, пауза/воспроизведение и следующий.
обработка клика:
Expand Collapse Copy
private void handleMediaClick(float mouseX, float mouseY) {
    if (currentSession == null || currentTrack == null) return;

    if (isInside(mouseX, mouseY, prevX, prevY, prevWidth)) {
        mediaExecutor.execute(currentSession::previous);
    } else if (isInside(mouseX, mouseY, playX, playY, playWidth)) {
        mediaExecutor.execute(() -> {
            if (currentTrack.getPlaying()) {
                currentSession.pause();
            } else {
                currentSession.play();
            }
        });
    } else if (isInside(mouseX, mouseY, nextX, nextY, nextWidth)) {
        mediaExecutor.execute(currentSession::next);
    }
}

Форматирование времени трека
форматирование:
Expand Collapse Copy
private String formatTime(long seconds) {
    if (seconds <= 0) return "0:00";
    long minutes = seconds / 60;
    long secs = seconds % 60;
    return String.format("%d:%02d", minutes, secs);
}
 
Назад
Сверху Снизу