325 lines
15 KiB
Markdown
325 lines
15 KiB
Markdown
# Spotify MC — Client-Side Spotify HUD for Minecraft
|
||
|
||
[](https://minecraft.net/)
|
||
[](https://fabricmc.net/)
|
||
[](https://adoptium.net/)
|
||
[](https://modrinth.com/mod/modmenu)
|
||
[](LICENSE)
|
||
|
||
A lightweight, high-performance, client-side Minecraft mod that brings real-time Spotify playback info, album art, and controls directly into your game HUD.
|
||
|
||
Built specifically for **Minecraft 1.21.1** using **Fabric Loader** and **Java 21**.
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [Overview](#overview)
|
||
- [Features](#features)
|
||
- [HUD Preview](#hud-preview)
|
||
- [Requirements](#requirements)
|
||
- [Player Installation](#player-installation)
|
||
- [Spotify Developer App Setup](#spotify-developer-app-setup)
|
||
- [Connecting In-Game](#connecting-in-game)
|
||
- [Controls & Commands](#controls--commands)
|
||
- [Configuration](#configuration)
|
||
- [Technical Architecture & Security](#technical-architecture--security)
|
||
- [Building from Source](#building-from-source)
|
||
- [Troubleshooting & FAQ](#troubleshooting--faq)
|
||
- [License](#license)
|
||
|
||
---
|
||
|
||
## Overview
|
||
|
||
**Spotify MC** connects directly to Spotify's Web API using secure **OAuth 2.0 PKCE** (Proof Key for Code Exchange) authentication. It allows you to view what is currently playing, inspect progress, and trigger playback controls from inside Minecraft without alt-tabbing or requiring external bridge apps.
|
||
|
||
### Highlights
|
||
- **Zero Native Dependencies**: Uses the built-in JDK `java.net.http.HttpClient` on background daemon threads.
|
||
- **Client-Side Only**: Does not need to be installed on servers. Play on any vanilla or modded server safely.
|
||
- **Battery & Performance Friendly**: Implements adaptive polling backoff (polls less frequently when paused or idle) and local linear progress extrapolation between ticks to eliminate lag spikes.
|
||
- **Privacy & Security First**: Tokens are encrypted locally with AES-GCM and never printed to crash logs or `latest.log`.
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
- **Dynamic HUD Overlay**:
|
||
- Displays song title, artist, and album name with customizable positioning.
|
||
- Automatic **marquee text scrolling** for long track titles and artist names.
|
||
- Asynchronously loaded and cached **album artwork** with memory-capped LRU texture eviction.
|
||
- Animated **progress bar** with real-time extrapolated smooth position updates and total duration (`mm:ss / mm:ss`).
|
||
- Playback status badge (`▶ Playing`, `⏸ Paused`, `⊘ No Player`, `! Offline`).
|
||
- Polished **glassmorphism** visual style with semi-transparent background and Spotify Green accent bars.
|
||
- **Configurable Keybinds**:
|
||
- Play / Pause Toggle
|
||
- Next Track / Previous Track
|
||
- Volume Up (+5%) / Volume Down (-5%)
|
||
- Toggle HUD overlay visibility on the fly
|
||
- **In-Game Chat Commands**:
|
||
- Full client-side `/spotify` command tree with tab completion.
|
||
- **In-Game GUI & ModMenu Integration**:
|
||
- Full interactive screen to input your Client ID, click to connect, adjust HUD scale (0.5x–2.0x), opacity (20%–100%), polling rate (1s–10s), screen anchor corners, and toggle artwork.
|
||
|
||
---
|
||
|
||
## HUD Preview
|
||
|
||
```text
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ ┌───────┐ ▶ Starboy (feat. Daft Punk) │
|
||
│ │ ALBUM │ The Weeknd — Starboy │
|
||
│ │ ART │ ━━━━━━━━━━━━━━━●──────────────────── 01:24 / 03:50│
|
||
│ └───────┘ Device: Desktop-PC (85% Vol) │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
The overlay anchors to any of the 4 screen corners (`TOP_LEFT`, `TOP_RIGHT`, `BOTTOM_LEFT`, `BOTTOM_RIGHT`) with adjustable offsets, scaling, and opacity.
|
||
|
||
---
|
||
|
||
## Requirements
|
||
|
||
| Requirement | Supported Version | Notes |
|
||
| :--- | :--- | :--- |
|
||
| **Minecraft** | `1.21.1` | Client-side only |
|
||
| **Fabric Loader** | `>= 0.16.0` | Standard Fabric installation |
|
||
| **Fabric API** | Latest for 1.21.1 | Required for HUD render callbacks |
|
||
| **Java Runtime** | `Java 21+` | Default for Minecraft 1.20.5+ |
|
||
| **ModMenu** | `11.0.2+` *(Optional)* | Enables in-game configuration UI from the mods list |
|
||
| **Spotify Account** | Free or Premium | *Note: Playback controls (play/pause/skip) require Spotify Premium per Spotify API terms; Free accounts can display track metadata and progress.* |
|
||
|
||
---
|
||
|
||
## Player Installation
|
||
|
||
1. Install **Fabric Loader** for Minecraft 1.21.1 from [fabricmc.net](https://fabricmc.net/).
|
||
2. Download the latest **Fabric API** from Modrinth or CurseForge.
|
||
3. Download `spotify-mc-1.2.1.jar` from the **Releases** tab of this repository.
|
||
4. Place both `.jar` files into your `.minecraft/mods/` folder:
|
||
- **Windows**: `%appdata%\.minecraft\mods\`
|
||
- **macOS**: `~/Library/Application Support/minecraft/mods/`
|
||
- **Linux**: `~/.minecraft/mods/`
|
||
5. Launch Minecraft using your Fabric profile.
|
||
|
||
---
|
||
|
||
## Spotify Developer App Setup
|
||
|
||
To connect the mod to your Spotify account, you need a free **Client ID** from Spotify:
|
||
|
||
1. Navigate to the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard) and log in.
|
||
2. Click **Create an App**.
|
||
3. Fill in the required fields:
|
||
- **App Name**: `Spotify MC` (or any label you prefer)
|
||
- **App Description**: `Minecraft client HUD integration`
|
||
- **Redirect URIs**: `http://127.0.0.1:8888/callback` *(**CRITICAL**: Must match character-for-character, no trailing slash!)*
|
||
- **Which API/SDKs are you planning to use?**: Select **Web API**.
|
||
4. Check the Developer Terms of Service checkbox and click **Save**.
|
||
5. Click **Settings** in the top right of your newly created application dashboard.
|
||
6. Copy your **Client ID** (a 32-character string).
|
||
> **Note on Client Secret**: This mod uses **OAuth 2.0 PKCE**. You do **NOT** need a client secret. Never share or paste your client secret anywhere.
|
||
|
||
---
|
||
|
||
## Connecting In-Game
|
||
|
||
1. Start Minecraft and enter any single-player world or multiplayer server.
|
||
2. Open the Spotify MC Configuration screen:
|
||
- Via **ModMenu**: Go to **Mods** -> **Spotify MC** -> Click the **Settings (gear)** icon.
|
||
- Or via chat: Type `/spotify connect` and press Enter.
|
||
3. Paste your **Client ID** into the Spotify Client ID box.
|
||
4. Click **Connect Spotify**.
|
||
5. Your default web browser will open Spotify's official authorization page.
|
||
6. Click **Agree** to authorize access.
|
||
7. The browser tab will display:
|
||
```
|
||
✓ Successfully Connected!
|
||
You can return to Minecraft now.
|
||
```
|
||
8. Return to Minecraft — your HUD will initialize and display your currently playing song!
|
||
|
||
---
|
||
|
||
## Controls & Commands
|
||
|
||
### In-Game Keybinds
|
||
By default, keybinds are left **Unassigned** so they do not conflict with your existing gameplay controls.
|
||
|
||
To assign them:
|
||
1. Open **Options** -> **Controls** -> **Key Binds**.
|
||
2. Scroll to the **Spotify MC** section.
|
||
3. Bind keys for:
|
||
- `Play / Pause`
|
||
- `Next Track`
|
||
- `Previous Track`
|
||
- `Toggle Spotify HUD`
|
||
- `Volume Up (+5%)`
|
||
- `Volume Down (-5%)`
|
||
|
||
### Chat Commands
|
||
All commands run entirely on the client:
|
||
|
||
| Command | Description |
|
||
| :--- | :--- |
|
||
| `/spotify status` | Prints current track title, artist, progress, and active device to chat |
|
||
| `/spotify play` | Resumes track playback |
|
||
| `/spotify pause` | Pauses track playback |
|
||
| `/spotify next` | Skips to the next track in queue |
|
||
| `/spotify previous` | Returns to the previous track |
|
||
| `/spotify hud` | Toggles the HUD overlay visibility |
|
||
| `/spotify connect` | Opens the configuration & OAuth login screen |
|
||
| `/spotify logout` | Disconnects your account and clears encrypted token storage |
|
||
|
||
---
|
||
|
||
## Configuration
|
||
|
||
Configuration is saved in `.minecraft/config/spotifymc/config.json`. You can modify it directly or through the in-game GUI:
|
||
|
||
```json
|
||
{
|
||
"clientId": "YOUR_SPOTIFY_CLIENT_ID",
|
||
"hudEnabled": true,
|
||
"showAlbumArt": true,
|
||
"autoHideWhenInactive": false,
|
||
"anchor": "TOP_LEFT",
|
||
"offsetX": 10,
|
||
"offsetY": 10,
|
||
"hudScale": 1.0,
|
||
"hudOpacity": 0.85,
|
||
"pollingIntervalSec": 2,
|
||
"accentColor": -14829228
|
||
}
|
||
```
|
||
|
||
### Config Options:
|
||
- **`hudEnabled`**: Master toggle for HUD rendering.
|
||
- **`showAlbumArt`**: When enabled, downloads and displays 48x48 album artwork.
|
||
- **`autoHideWhenInactive`**: Automatically hides the overlay when playback is stopped or no player is active.
|
||
- **`anchor`**: `TOP_LEFT`, `TOP_RIGHT`, `BOTTOM_LEFT`, or `BOTTOM_RIGHT`.
|
||
- **`offsetX` / `offsetY`**: Pixel margin from the chosen anchor corner.
|
||
- **`hudScale`**: HUD sizing factor (`0.5x` to `2.0x`).
|
||
- **`hudOpacity`**: Glassmorphic background opacity (`20%` to `100%`).
|
||
- **`pollingIntervalSec`**: Polling frequency in seconds (`1` to `10`).
|
||
|
||
---
|
||
|
||
## Technical Architecture & Security
|
||
|
||
```
|
||
spotify-mc/
|
||
├── .gitattributes # Line endings & binary rules
|
||
├── .gitignore # Excludes credentials, build caches, and jars
|
||
├── LICENSE # MIT License
|
||
├── README.md # Project documentation
|
||
├── build.gradle # Fabric Loom build script
|
||
├── gradle.properties # Project and dependency versions
|
||
├── settings.gradle # Project settings
|
||
├── gradlew & gradlew.bat # Gradle wrapper execution scripts
|
||
├── gradle/wrapper/
|
||
│ ├── gradle-wrapper.jar
|
||
│ └── gradle-wrapper.properties
|
||
└── src/
|
||
├── main/
|
||
│ ├── resources/
|
||
│ │ ├── fabric.mod.json # Mod metadata & entrypoints
|
||
│ │ └── assets/spotifymc/
|
||
│ │ ├── icon.png # 64x64 Mod icon
|
||
│ │ └── lang/en_us.json # Localization translations
|
||
│ └── java/com/spotifymc/
|
||
│ ├── SpotifyMod.java # Mod entrypoint & client lifecycle
|
||
│ ├── auth/
|
||
│ │ ├── PkceUtils.java # RFC 7636 SHA-256 verifier & challenge
|
||
│ │ ├── LocalCallbackServer.java # Ephemeral 127.0.0.1:8888 listener
|
||
│ │ ├── TokenStorage.java # AES-GCM encrypted local credential store
|
||
│ │ └── SpotifyAuthManager.java # Token lifecycle & automatic background refresh
|
||
│ ├── api/
|
||
│ │ ├── SpotifyDevice.java # Active device record
|
||
│ │ ├── SpotifyPlaybackState.java # Extrapolated playback state
|
||
│ │ └── SpotifyApiClient.java # Non-blocking JDK HttpClient & 429 backoff
|
||
│ ├── playback/
|
||
│ │ └── SpotifyPlaybackManager.java # Adaptive polling coordinator
|
||
│ ├── hud/
|
||
│ │ ├── AlbumArtCache.java # Asynchronous LRU texture loader
|
||
│ │ └── SpotifyHudRenderer.java # Glassmorphic HUD renderer
|
||
│ ├── keybinds/
|
||
│ │ └── SpotifyKeybindHandler.java # Keybind triggers & repeat filters
|
||
│ ├── commands/
|
||
│ │ └── SpotifyCommands.java # Fabric client command registrations
|
||
│ └── config/
|
||
│ ├── SpotifyConfig.java # Config serialization & defaults
|
||
│ ├── SpotifyConfigScreen.java # Native GUI screen & interactive widgets
|
||
│ └── ModMenuIntegration.java # ModMenu API entrypoint
|
||
└── test/java/com/spotifymc/auth/
|
||
├── PkceUtilsTest.java # Validates RFC 7636 Appendix B test vector
|
||
└── TokenStorageTest.java # Validates AES-GCM encryption & redaction
|
||
```
|
||
|
||
### Security Measures
|
||
1. **RFC 7636 PKCE Authentication**:
|
||
- The Authorization Code flow with PKCE ensures code interception attacks are impossible without needing an embedded client secret.
|
||
2. **AES-GCM Local Credential Encryption**:
|
||
- Spotify access and refresh tokens are stored in `credentials.json` encrypted with **AES-GCM (128-bit authentication tag)** using a local hardware-derived key.
|
||
3. **Sensitive Information Redaction**:
|
||
- All token storage objects, HTTP logs, and debug strings redact authorization tokens as `[REDACTED]`. Tokens are never exposed in crash reports or logs.
|
||
4. **Git Protection**:
|
||
- The repository's `.gitignore` explicitly prevents accidental commits of credentials, tokens, logs, and development runs.
|
||
|
||
---
|
||
|
||
## Building from Source
|
||
|
||
### Prerequisites
|
||
- **Java 21 JDK** or newer (e.g. [Eclipse Temurin 21](https://adoptium.net/temurin/releases/?version=21))
|
||
- **Git**
|
||
|
||
### Clone & Build
|
||
```bash
|
||
# Clone the repository
|
||
git clone https://gitea.jadonsandbox.com/jkortis/spotify-mc.git
|
||
cd spotify-mc
|
||
|
||
# Run tests
|
||
./gradlew test # On Linux / macOS
|
||
.\gradlew.bat test # On Windows
|
||
|
||
# Launch Minecraft development client
|
||
./gradlew runClient # On Linux / macOS
|
||
.\gradlew.bat runClient # On Windows
|
||
|
||
# Build the distributable mod JAR
|
||
./gradlew build # On Linux / macOS
|
||
.\gradlew.bat build # On Windows
|
||
```
|
||
|
||
The output JAR will be placed in `build/libs/spotify-mc-1.2.1.jar`.
|
||
|
||
---
|
||
|
||
## Troubleshooting & FAQ
|
||
|
||
### 1. HTTP 403 Forbidden ("Spotify Premium is required for playback controls")
|
||
- **Cause**: Spotify API policies restrict playback modification endpoints (`play`, `pause`, `next`, `previous`, `volume`) to accounts with an active **Spotify Premium** subscription.
|
||
- **Solution**: Free Spotify accounts can still view song titles, artist names, album art, and progress bar. If you have Premium, verify you are logged into the correct Spotify account in your browser.
|
||
|
||
### 2. HTTP 404 / 204 ("No Active Player")
|
||
- **Cause**: Spotify has no active playback session on any device.
|
||
- **Solution**: Open the Spotify Desktop app, Web player, or mobile app and start playing a track. Once Spotify registers an active player, the mod will instantly lock on.
|
||
|
||
### 3. Browser Redirect / Port 8888 Conflict
|
||
- **Cause**: Another service is using port 8888, or the redirect URI in the developer dashboard has a typo.
|
||
- **Solution**:
|
||
- Verify that the redirect URI in your [Spotify Developer Dashboard](https://developer.spotify.com/dashboard) is **exactly** `http://127.0.0.1:8888/callback` (case-sensitive, no spaces, no trailing slash).
|
||
- Ensure no other local proxy or web server is holding port 8888.
|
||
|
||
### 4. HTTP 429 Too Many Requests ("Rate Limited")
|
||
- **Cause**: Spotify Web API temporary rate limit reached.
|
||
- **Solution**: Spotify MC features built-in adaptive rate-limiting backoff. It automatically reads the `Retry-After` header and pauses polling until the cooldown expires.
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
This project is licensed under the [MIT License](LICENSE).
|