🐾CatSkinC – Easy Minecraft Skin Manager
Upload your own skin from inside the game and have everyone see it instantly — no server-side setup, works on any server.
CatSkinC is a client-side skin mod. Press a key, drop a PNG, and your skin is uploaded to the CatSkinC cloud and pushed live to every other player running the mod. It even gives your character a talking mouth that moves while you speak in voice chat.
This mod is designed for players who frequently switch skins, artists who create high-detail textures, and anyone who wants more control and flexibility over their Minecraft appearance.
✨ Features
- 🎨 In-game skin upload — press
Kto open the workspace, then drag-and-drop a PNG. No website, no relog. - 🌍 Live sync for everyone — when you change your skin, every player with the mod sees it update in real time (Server-Sent Events under the hood).
- 🗣️ Talking mouths — add optional mouth-open / mouth-close overlay images and your skin's mouth animates while you talk in voice chat.
- 🖼️ Local library — your uploaded skins are kept in a reusable library with thumbnails, quick re-select, and delete.
- 👤 Live 3D preview — preview skins on a rotatable player model before you commit, with a dedicated Slim / Wide model toggle.
- 🧩 Plays nice with other mods — built-in compatibility with Figura, plus soft integration with Simple Voice Chat and Plasmo Voice.
- 🔒 Secure by design — identity is verified through Mojang, transfers are HTTPS-only with integrity checks, and only premium accounts can upload.
🎮 How it works
- Install the mod on your client (and any friends who want to see custom skins).
- Join any world or server.
- Press
K, drag in a PNG skin (64×64 or higher, square, power-of-two). - (Optional) Add mouth-open / mouth-close overlays for the talking effect.
- Pick Slim or Wide, hit upload — done. Everyone running the mod sees it live.
Skin data travels through the CatSkinC cloud, not the Minecraft server — so the people you play with sync skins peer-to-peer regardless of what server you're on.
📦 Requirements
This is a client-side mod — you do NOT need to install it on your Minecraft server. Vanilla servers are fine.
| Required | |
|---|---|
| Fabric API | ✅ Yes |
| Architectury API | ✅ Yes |
| Account | Premium / Mojang account (offline/cracked uploads are rejected) |
Supported versions & loaders
| Minecraft | Loaders |
|---|---|
| 1.21.1 | Fabric, NeoForge |
| 1.20.1 | Fabric, Forge |
Players without the mod simply see you with your normal vanilla skin — nothing breaks for them.
🔌 Optional integrations (install only if you want them)
- Simple Voice Chat / Plasmo Voice — drives the talking-mouth animation from your real voice activity.
- Figura — fully compatible. If you have an active Figura avatar, CatSkinC steps aside and lets Figura render your character, so the two never fight over your skin.
- Emotecraft — detected and supported alongside emotes.
All of these are soft dependencies: if they aren't installed, CatSkinC just runs without those features.
❓ FAQ
Do I need this on the server? No. It's purely client-side. Install it on each player's game.
Will players without the mod see my skin? No — they'll see your default vanilla skin. Only players with CatSkinC installed see custom skins.
Does it work with shaders / Figura / voice mods? Yes. Figura takes priority when you have an avatar loaded, and voice mods power the mouth animation.
My skin won't upload? Make sure you're on a premium (paid) Minecraft account and your image is a square PNG sized to a power of two (64, 128, 256, …).
🔧Compatibility
- Minecraft: Java Edition (tested on 1.20.x & 1.21.x)
- Loaders: Fabric,Forge,NeoForge
- Environment: Client-side only
ℹ️Notes
- Skin data is managed via Cloud (stored and retrieved online)
- Client-only mod, no server-side installation required
- One player = one skin file (but can store unlimited file)
Community & Development
CatSkinC is community-friendly and open source. You can:
- community on Discord
- Report bugs or request features on GitHub Issues
- Explore or contribute at the GitHub Repository
📜 License
Made by Cat Lab_ 9Creations Club (Q Team Studio).
All Versions
+ Add Version| Name | Game version | Platforms | Published | Downloads | Actions |
|---|---|---|---|---|---|
| 26d ago | 1 | ||||
| 26d ago | 1 | ||||
| 26d ago | 1 | ||||
| 26d ago | 1 | ||||
| 1mo ago | 1 | ||||
| 1mo ago | 1 | ||||
| 1mo ago | 1 | ||||
| 1mo ago | 1 | ||||
| 1mo ago | 1 | ||||
| 1mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 5mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 6mo ago | 1 | ||||
| 8mo ago | 1 | ||||
| 8mo ago | 1 | ||||
| 8mo ago | 1 | ||||
| 8mo ago | 1 | ||||
| 8mo ago | 1 | ||||
| 8mo ago | 1 | ||||
| 8mo ago | 1 | ||||
| 8mo ago | 1 | ||||
| 11mo ago | 1 | ||||
| 11mo ago | 1 | ||||
| 11mo ago | 1 | ||||
| 11mo ago | 1 | ||||
| 11mo ago | 1 | ||||
| 11mo ago | 1 | ||||
| last yr. | 1 | ||||
| last yr. | 1 |
- Skin update events now bypass the short-lived selected-skin cache, so changed
- Force-refresh events received during an active fetch are coalesced into a
- Skin update events now bypass the short-lived selected-skin cache, so changed
- Force-refresh events received during an active fetch are coalesced into a
- Skin update events now bypass the short-lived selected-skin cache, so changed
- Force-refresh events received during an active fetch are coalesced into a
- Skin update events now bypass the short-lived selected-skin cache, so changed
- Force-refresh events received during an active fetch are coalesced into a
- Fixed the Myopia settings category so it can be expanded and its controls respond to clicks.
- Fixed the Request Signing Key row label and reset button, and hide its input when General is collapsed.
- Fixed the Myopia settings category so it can be expanded and its controls respond to clicks.
- Fixed the Request Signing Key row label and reset button, and hide its input when General is collapsed.
- WebSocket client** using native
java.net.http.WebSocket(Java 11+) for high-performance real-time skin sync. - Automatic protocol negotiation** — client sends
x-catskinc-protocol: 3header on WebSocket handshake. - Resilient connection management**:
- Exponential backoff reconnection (1.5s → 60s max).
- Shared circuit breaker across REST, SSE, and WebSocket (unified failure tracking).
- Automatic fallback to SSE when WebSocket fails or protocol is unsupported.
- Session-token authentication** on WebSocket with auto-subscription to local player UUID.
- Protocol version verification** in welcome message — closes connection on mismatch.
- In-game toast notifications** for WebSocket-originated events (skin updates, server messages).
- Myopia skin LOD** for CatSkinC-managed remote skins. When enabled, distant
copies while GUI, inventory, and tab-list skins retain full resolution.
- A Myopia settings screen with an enabled toggle, a 4–128 block base-distance
- Default keybindings for increasing and decreasing the Myopia range with the
catskinc.json.### Changed
- Join flow** now attempts WebSocket first, falls back to SSE on failure.
- Shared circuit breaker state** between
ServerApiClientandWebSocketClient— REST/SSE/WS failures all contribute to the same breaker. - Heartbeat handling** — application-level JSON ping/pong (30s) replaces binary WebSocket ping frames for consistency.
### Fixed
- Broadcast framing** — WebSocket clients now receive raw JSON (SSE
data:prefix stripped server-side). - Handshake protocol header** — added
X-CatSkinC-Protocolto WebSocket upgrade request. - Auth race** — session token acquired synchronously before WebSocket connection attempt.
- Protocol defense** — client verifies
protocol_versionin welcome message, closes on mismatch. - Fallback trigger** — SSE fallback now activates on abnormal post-connect disconnections, not just initial connect failure.
- Toast handler** — implemented proper
Toasts.info()with translatable titles. - Select-Fetch race eliminated**:
selectSkin()now chainsthenRun(refresh)so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - Pending selections cache**:
PENDING_SELECTIONSreturns the uploaded skin URL immediately after select, avoiding old-skin flashing. - LAST_CHECK on success only**: failed fetches no longer reset the 5s poll timer, preventing a 15s blackout window.
- Fast-retry after null skin**: retries fetch in 2s when the server has no cached skin yet, reducing initial sync from 15s to 2s.
- Poll interval reduced**: 15s → 5s for faster periodic sync.
- SSE clear-skin handling**: clears
BASE_CACHE/TALKING_CACHEon null URL, so players properly revert to the default skin. - SSE reconnect delay**: added 1.5s–60s exponential backoff on stream close (was instant reconnect), preventing server flooding.
- Circuit breaker in SSE**: SSE checks
circuitOpenUntilMsbefore connecting, eliminating useless retries during outage. - AtomicInteger**:
consecutiveFailuresswitched toAtomicIntegerfor correct failure counting. - Always destroy old textures**: removed identity check gate on texture release to prevent GPU memory leaks.
- Fixed HTTP 401 on skin downloads**: Added
signDownloadUrl()method that appends?exp=&sig=HMAC-signed query parameters to download URLs using the client'srequestSigningKey. This matches the server'sverify_download_signature()check whenENFORCE_SIGNED_DOWNLOADS=true. - Replaced per-player TextureManager registrations with a single shared dynamic texture**: CatSkinC no longer registers per-player textures with the vanilla
TextureManager. DownloadedNativeImageobjects are cached and pixel-copied into one sharedcatskinc:dynamic/activetexture on each render frame. This prevents F3+S debug dumps from saving every player's skin to disk. - Security**: **Request signing** (HMAC-SHA256) applied to WebSocket upgrade request.
- Hardened transitive dependencies against Dependabot advisories.** Added
resolutionStrategy { force ... }constraints inbuild.gradleto pin patched versions of vulnerable transitive libraries on both the project and buildscript classpaths: - Netty →
4.1.136.Final(fixes GHSA-558v-64gr-wgg4 Bzip2Decoder infinite loop and related netty advisories). - Log4j →
2.25.4(fixes Log4j TLS hostname verification, XML escaping, and related advisories). - Guava →
32.0.0-jre(fixes temp-dir and information-disclosure advisories). - Commons IO →
2.16.1, Commons Compress →1.26.0, Commons Lang3 →3.18.0. - Buildscript classpath: Commons Text →
1.12.0, Commons Beanutils →1.11.0, Plexus Utils →3.6.1. - These libraries are Minecraft-provided runtime/build-tooling dependencies and are **not bundled** into the shipped mod JAR, so the end-user artifact is unaffected; the constraints keep the dev runtime and CI dependency graph clean.
- WebSocket client** using native
java.net.http.WebSocket(Java 11+) for high-performance real-time skin sync. - Automatic protocol negotiation** — client sends
x-catskinc-protocol: 3header on WebSocket handshake. - Resilient connection management**:
- Exponential backoff reconnection (1.5s → 60s max).
- Shared circuit breaker across REST, SSE, and WebSocket (unified failure tracking).
- Automatic fallback to SSE when WebSocket fails or protocol is unsupported.
- Session-token authentication** on WebSocket with auto-subscription to local player UUID.
- Protocol version verification** in welcome message — closes connection on mismatch.
- In-game toast notifications** for WebSocket-originated events (skin updates, server messages).
- Myopia skin LOD** for CatSkinC-managed remote skins. When enabled, distant
copies while GUI, inventory, and tab-list skins retain full resolution.
- A Myopia settings screen with an enabled toggle, a 4–128 block base-distance
- Default keybindings for increasing and decreasing the Myopia range with the
catskinc.json.### Changed
- Join flow** now attempts WebSocket first, falls back to SSE on failure.
- Shared circuit breaker state** between
ServerApiClientandWebSocketClient— REST/SSE/WS failures all contribute to the same breaker. - Heartbeat handling** — application-level JSON ping/pong (30s) replaces binary WebSocket ping frames for consistency.
### Fixed
- Broadcast framing** — WebSocket clients now receive raw JSON (SSE
data:prefix stripped server-side). - Handshake protocol header** — added
X-CatSkinC-Protocolto WebSocket upgrade request. - Auth race** — session token acquired synchronously before WebSocket connection attempt.
- Protocol defense** — client verifies
protocol_versionin welcome message, closes on mismatch. - Fallback trigger** — SSE fallback now activates on abnormal post-connect disconnections, not just initial connect failure.
- Toast handler** — implemented proper
Toasts.info()with translatable titles. - Select-Fetch race eliminated**:
selectSkin()now chainsthenRun(refresh)so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - Pending selections cache**:
PENDING_SELECTIONSreturns the uploaded skin URL immediately after select, avoiding old-skin flashing. - LAST_CHECK on success only**: failed fetches no longer reset the 5s poll timer, preventing a 15s blackout window.
- Fast-retry after null skin**: retries fetch in 2s when the server has no cached skin yet, reducing initial sync from 15s to 2s.
- Poll interval reduced**: 15s → 5s for faster periodic sync.
- SSE clear-skin handling**: clears
BASE_CACHE/TALKING_CACHEon null URL, so players properly revert to the default skin. - SSE reconnect delay**: added 1.5s–60s exponential backoff on stream close (was instant reconnect), preventing server flooding.
- Circuit breaker in SSE**: SSE checks
circuitOpenUntilMsbefore connecting, eliminating useless retries during outage. - AtomicInteger**:
consecutiveFailuresswitched toAtomicIntegerfor correct failure counting. - Always destroy old textures**: removed identity check gate on texture release to prevent GPU memory leaks.
- Fixed HTTP 401 on skin downloads**: Added
signDownloadUrl()method that appends?exp=&sig=HMAC-signed query parameters to download URLs using the client'srequestSigningKey. This matches the server'sverify_download_signature()check whenENFORCE_SIGNED_DOWNLOADS=true. - Replaced per-player TextureManager registrations with a single shared dynamic texture**: CatSkinC no longer registers per-player textures with the vanilla
TextureManager. DownloadedNativeImageobjects are cached and pixel-copied into one sharedcatskinc:dynamic/activetexture on each render frame. This prevents F3+S debug dumps from saving every player's skin to disk. - Security**: **Request signing** (HMAC-SHA256) applied to WebSocket upgrade request.
- Hardened transitive dependencies against Dependabot advisories.** Added
resolutionStrategy { force ... }constraints inbuild.gradleto pin patched versions of vulnerable transitive libraries on both the project and buildscript classpaths: - Netty →
4.1.136.Final(fixes GHSA-558v-64gr-wgg4 Bzip2Decoder infinite loop and related netty advisories). - Log4j →
2.25.4(fixes Log4j TLS hostname verification, XML escaping, and related advisories). - Guava →
32.0.0-jre(fixes temp-dir and information-disclosure advisories). - Commons IO →
2.16.1, Commons Compress →1.26.0, Commons Lang3 →3.18.0. - Buildscript classpath: Commons Text →
1.12.0, Commons Beanutils →1.11.0, Plexus Utils →3.6.1. - These libraries are Minecraft-provided runtime/build-tooling dependencies and are **not bundled** into the shipped mod JAR, so the end-user artifact is unaffected; the constraints keep the dev runtime and CI dependency graph clean.
- Myopia skin LOD** for CatSkinC-managed remote skins. When enabled, distant
copies while GUI, inventory, and tab-list skins retain full resolution.
- A Myopia settings screen with an enabled toggle, a 4–128 block base-distance
- Default keybindings for increasing and decreasing the Myopia range with the
catskinc.json.- WebSocket client** using native
java.net.http.WebSocket(Java 11+) for high-performance real-time skin sync. - Automatic protocol negotiation** — client sends
x-catskinc-protocol: 3header on WebSocket handshake. - Resilient connection management**:
- Exponential backoff reconnection (1.5s → 60s max).
- Shared circuit breaker across REST, SSE, and WebSocket (unified failure tracking).
- Automatic fallback to SSE when WebSocket fails or protocol is unsupported.
- Session-token authentication** on WebSocket with auto-subscription to local player UUID.
- Protocol version verification** in welcome message — closes connection on mismatch.
- In-game toast notifications** for WebSocket-originated events (skin updates, server messages).
### Changed
- Join flow** now attempts WebSocket first, falls back to SSE on failure.
- Shared circuit breaker state** between
ServerApiClientandWebSocketClient— REST/SSE/WS failures all contribute to the same breaker. - Heartbeat handling** — application-level JSON ping/pong (30s) replaces binary WebSocket ping frames for consistency.
- Managed-skin texture cleanup** now also releases all associated Myopia GPU
### Fixed
- Broadcast framing** — WebSocket clients now receive raw JSON (SSE
data:prefix stripped server-side). - Handshake protocol header** — added
X-CatSkinC-Protocolto WebSocket upgrade request. - Auth race** — session token acquired synchronously before WebSocket connection attempt.
- Protocol defense** — client verifies
protocol_versionin welcome message, closes on mismatch. - Fallback trigger** — SSE fallback now activates on abnormal post-connect disconnections, not just initial connect failure.
- Toast handler** — implemented proper
Toasts.info()with translatable titles. - Select-Fetch race eliminated**:
selectSkin()now chainsthenRun(refresh)so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - Pending selections cache**:
PENDING_SELECTIONSreturns the uploaded skin URL immediately after select, avoiding old-skin flashing. - LAST_CHECK on success only**: failed fetches no longer reset the 5s poll timer, preventing a 15s blackout window.
- Fast-retry after null skin**: retries fetch in 2s when the server has no cached skin yet, reducing initial sync from 15s to 2s.
- Poll interval reduced**: 15s → 5s for faster periodic sync.
- SSE clear-skin handling**: clears
BASE_CACHE/TALKING_CACHEon null URL, so players properly revert to the default skin. - SSE reconnect delay**: added 1.5s–60s exponential backoff on stream close (was instant reconnect), preventing server flooding.
- Circuit breaker in SSE**: SSE checks
circuitOpenUntilMsbefore connecting, eliminating useless retries during outage. - AtomicInteger**:
consecutiveFailuresswitched toAtomicIntegerfor correct failure counting. - Always destroy old textures**: removed identity check gate on texture release to prevent GPU memory leaks.
- Fixed HTTP 401 on skin downloads**: Added
signDownloadUrl()method that appends?exp=&sig=HMAC-signed query parameters to download URLs using the client'srequestSigningKey. This matches the server'sverify_download_signature()check whenENFORCE_SIGNED_DOWNLOADS=true. - Replaced per-player TextureManager registrations with a single shared dynamic texture**: CatSkinC no longer registers per-player textures (
catskinc:remote/<uuid>) with the vanillaTextureManager. Instead, downloadedNativeImageobjects are cached inSKIN_IMAGESand pixel-copied into one sharedcatskinc:dynamic/activetexture on each render frame. This prevents F3+S debug dumps from saving every player's skin to disk. - Broadcast framing** — WebSocket clients now receive raw JSON (SSE
data:prefix stripped server-side). - Handshake protocol header** — added
X-CatSkinC-Protocolto WebSocket upgrade request. - Auth race** — session token acquired synchronously before WebSocket connection attempt.
- Protocol defense** — client verifies
protocol_versionin welcome message, closes on mismatch. - Fallback trigger** — SSE fallback now activates on abnormal post-connect disconnections, not just initial connect failure.
- Toast handler** — implemented proper
Toasts.info()with translatable titles. - Select-Fetch race eliminated**:
selectSkin()now chainsthenRun(refresh)so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - Pending selections cache**:
PENDING_SELECTIONSreturns the uploaded skin URL immediately after select, avoiding old-skin flashing. - LAST_CHECK on success only**: failed fetches no longer reset the 5s poll timer, preventing a 15s blackout window.
- Fast-retry after null skin**: retries fetch in 2s when the server has no cached skin yet, reducing initial sync from 15s to 2s.
- Poll interval reduced**: 15s → 5s for faster periodic sync.
- SSE clear-skin handling**: clears
BASE_CACHE/TALKING_CACHEon null URL, so players properly revert to the default skin. - SSE reconnect delay**: added 1.5s–60s exponential backoff on stream close (was instant reconnect), preventing server flooding.
- Circuit breaker in SSE**: SSE checks
circuitOpenUntilMsbefore connecting, eliminating useless retries during outage. - AtomicInteger**:
consecutiveFailuresswitched toAtomicIntegerfor correct failure counting. - Always destroy old textures**: removed identity check gate on texture release to prevent GPU memory leaks.
- Fixed HTTP 401 on skin downloads**: Added
signDownloadUrl()method that appends?exp=&sig=HMAC-signed query parameters to download URLs using the client'srequestSigningKey. This matches the server'sverify_download_signature()check whenENFORCE_SIGNED_DOWNLOADS=true. - Replaced per-player TextureManager registrations with a single shared dynamic texture**: CatSkinC no longer registers per-player textures (
catskinc:remote/<uuid>) with the vanillaTextureManager. Instead, downloadedNativeImageobjects are cached inSKIN_IMAGESand pixel-copied into one sharedcatskinc:dynamic/activetexture on each render frame. This prevents F3+S debug dumps from saving every player's skin to disk. - Security**: **Request signing** (HMAC-SHA256) applied to WebSocket upgrade request.
- Hardened transitive dependencies against Dependabot advisories.** Added
resolutionStrategy { force ... }constraints inbuild.gradleto pin patched versions of vulnerable transitive libraries on both the project and buildscript classpaths: - Netty →
4.1.136.Final(fixes GHSA-558v-64gr-wgg4 Bzip2Decoder infinite loop and related netty advisories). - Log4j →
2.25.4(fixes Log4j TLS hostname verification, XML escaping, and related advisories). - Guava →
32.0.0-jre(fixes temp-dir and information-disclosure advisories). - Commons IO →
2.16.1, Commons Compress →1.26.0, Commons Lang3 →3.18.0. - Buildscript classpath: Commons Text →
1.12.0, Commons Beanutils →1.11.0, Plexus Utils →3.6.1. - These libraries are Minecraft-provided runtime/build-tooling dependencies and are **not bundled** into the shipped mod JAR, so the end-user artifact is unaffected; the constraints keep the dev runtime and CI dependency graph clean.
- Myopia skin LOD** for CatSkinC-managed remote skins. When enabled, distant
copies while GUI, inventory, and tab-list skins retain full resolution.
- A Myopia settings screen with an enabled toggle, a 4–128 block base-distance
- Default keybindings for increasing and decreasing the Myopia range with the
catskinc.json.- WebSocket client** using native
java.net.http.WebSocket(Java 11+) for high-performance real-time skin sync. - Automatic protocol negotiation** — client sends
x-catskinc-protocol: 3header on WebSocket handshake. - Resilient connection management**:
- Exponential backoff reconnection (1.5s → 60s max).
- Shared circuit breaker across REST, SSE, and WebSocket (unified failure tracking).
- Automatic fallback to SSE when WebSocket fails or protocol is unsupported.
- Session-token authentication** on WebSocket with auto-subscription to local player UUID.
- Protocol version verification** in welcome message — closes connection on mismatch.
- In-game toast notifications** for WebSocket-originated events (skin updates, server messages).
### Changed
- Join flow** now attempts WebSocket first, falls back to SSE on failure.
- Shared circuit breaker state** between
ServerApiClientandWebSocketClient— REST/SSE/WS failures all contribute to the same breaker. - Heartbeat handling** — application-level JSON ping/pong (30s) replaces binary WebSocket ping frames for consistency.
- Managed-skin texture cleanup** now also releases all associated Myopia GPU
### Fixed
- Broadcast framing** — WebSocket clients now receive raw JSON (SSE
data:prefix stripped server-side). - Handshake protocol header** — added
X-CatSkinC-Protocolto WebSocket upgrade request. - Auth race** — session token acquired synchronously before WebSocket connection attempt.
- Protocol defense** — client verifies
protocol_versionin welcome message, closes on mismatch. - Fallback trigger** — SSE fallback now activates on abnormal post-connect disconnections, not just initial connect failure.
- Toast handler** — implemented proper
Toasts.info()with translatable titles. - Select-Fetch race eliminated**:
selectSkin()now chainsthenRun(refresh)so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - Pending selections cache**:
PENDING_SELECTIONSreturns the uploaded skin URL immediately after select, avoiding old-skin flashing. - LAST_CHECK on success only**: failed fetches no longer reset the 5s poll timer, preventing a 15s blackout window.
- Fast-retry after null skin**: retries fetch in 2s when the server has no cached skin yet, reducing initial sync from 15s to 2s.
- Poll interval reduced**: 15s → 5s for faster periodic sync.
- SSE clear-skin handling**: clears
BASE_CACHE/TALKING_CACHEon null URL, so players properly revert to the default skin. - SSE reconnect delay**: added 1.5s–60s exponential backoff on stream close (was instant reconnect), preventing server flooding.
- Circuit breaker in SSE**: SSE checks
circuitOpenUntilMsbefore connecting, eliminating useless retries during outage. - AtomicInteger**:
consecutiveFailuresswitched toAtomicIntegerfor correct failure counting. - Always destroy old textures**: removed identity check gate on texture release to prevent GPU memory leaks.
- Fixed HTTP 401 on skin downloads**: Added
signDownloadUrl()method that appends?exp=&sig=HMAC-signed query parameters to download URLs using the client'srequestSigningKey. This matches the server'sverify_download_signature()check whenENFORCE_SIGNED_DOWNLOADS=true. - Replaced per-player TextureManager registrations with a single shared dynamic texture**: CatSkinC no longer registers per-player textures (
catskinc:remote/<uuid>) with the vanillaTextureManager. Instead, downloadedNativeImageobjects are cached inSKIN_IMAGESand pixel-copied into one sharedcatskinc:dynamic/activetexture on each render frame. This prevents F3+S debug dumps from saving every player's skin to disk. - Broadcast framing** — WebSocket clients now receive raw JSON (SSE
data:prefix stripped server-side). - Handshake protocol header** — added
X-CatSkinC-Protocolto WebSocket upgrade request. - Auth race** — session token acquired synchronously before WebSocket connection attempt.
- Protocol defense** — client verifies
protocol_versionin welcome message, closes on mismatch. - Fallback trigger** — SSE fallback now activates on abnormal post-connect disconnections, not just initial connect failure.
- Toast handler** — implemented proper
Toasts.info()with translatable titles. - Select-Fetch race eliminated**:
selectSkin()now chainsthenRun(refresh)so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - Pending selections cache**:
PENDING_SELECTIONSreturns the uploaded skin URL immediately after select, avoiding old-skin flashing. - LAST_CHECK on success only**: failed fetches no longer reset the 5s poll timer, preventing a 15s blackout window.
- Fast-retry after null skin**: retries fetch in 2s when the server has no cached skin yet, reducing initial sync from 15s to 2s.
- Poll interval reduced**: 15s → 5s for faster periodic sync.
- SSE clear-skin handling**: clears
BASE_CACHE/TALKING_CACHEon null URL, so players properly revert to the default skin. - SSE reconnect delay**: added 1.5s–60s exponential backoff on stream close (was instant reconnect), preventing server flooding.
- Circuit breaker in SSE**: SSE checks
circuitOpenUntilMsbefore connecting, eliminating useless retries during outage. - AtomicInteger**:
consecutiveFailuresswitched toAtomicIntegerfor correct failure counting. - Always destroy old textures**: removed identity check gate on texture release to prevent GPU memory leaks.
- Fixed HTTP 401 on skin downloads**: Added
signDownloadUrl()method that appends?exp=&sig=HMAC-signed query parameters to download URLs using the client'srequestSigningKey. This matches the server'sverify_download_signature()check whenENFORCE_SIGNED_DOWNLOADS=true. - Replaced per-player TextureManager registrations with a single shared dynamic texture**: CatSkinC no longer registers per-player textures (
catskinc:remote/<uuid>) with the vanillaTextureManager. Instead, downloadedNativeImageobjects are cached inSKIN_IMAGESand pixel-copied into one sharedcatskinc:dynamic/activetexture on each render frame. This prevents F3+S debug dumps from saving every player's skin to disk. - Security**: **Request signing** (HMAC-SHA256) applied to WebSocket upgrade request.
- Hardened transitive dependencies against Dependabot advisories.** Added
resolutionStrategy { force ... }constraints inbuild.gradleto pin patched versions of vulnerable transitive libraries on both the project and buildscript classpaths: - Netty →
4.1.136.Final(fixes GHSA-558v-64gr-wgg4 Bzip2Decoder infinite loop and related netty advisories). - Log4j →
2.25.4(fixes Log4j TLS hostname verification, XML escaping, and related advisories). - Guava →
32.0.0-jre(fixes temp-dir and information-disclosure advisories). - Commons IO →
2.16.1, Commons Compress →1.26.0, Commons Lang3 →3.18.0. - Buildscript classpath: Commons Text →
1.12.0, Commons Beanutils →1.11.0, Plexus Utils →3.6.1. - These libraries are Minecraft-provided runtime/build-tooling dependencies and are **not bundled** into the shipped mod JAR, so the end-user artifact is unaffected; the constraints keep the dev runtime and CI dependency graph clean.
### Added
- Added editable
catskinCloudIpsetting to specify custom server addresses. The server URL is automatically normalized and prepended with a protocol (http://orhttps://) if missing. - Added toggle settings to selectively enable or disable various toast notifications (
showConnectionToast,showUploadToast,showInfoToast, andshowErrorToast). - Added the original button click sound to the Slim Model toggle switch.
### Changed
- Redesigned the client Settings screen: replaced the dropdown menu with search-filterable and collapsible accordion categories.
- Replaced the library slot thumbnail rendering with a 2D player face (matching the Tab Server List appearance) utilizing
PlayerFaceExtractorto integrate with Minecraft's deferred PiP rendering pipeline. - Shortened Toast messages in English and Thai language files to prevent text overflowing the toast boxes.
### Fixed
- Decoupled connection checks from skin downloads: increased client concurrent connection limit to 50 and executed pings on a separate thread pool to ensure player skins load instantly without queueing.
- Fixed the "Clear Skin" action: attached the Mojang verification session token to clear selection requests to prevent HTTP 401 Unauthorized errors on session-enforced servers.
- Fixed skin texture registration issues by utilizing a 2-argument
ResourceTextureconstructor to prevent path modification.
### Added
- Added editable
catskinCloudIpsetting to specify custom server addresses. The server URL is automatically normalized and prepended with a protocol (http://orhttps://) if missing. - Added toggle settings to selectively enable or disable various toast notifications (
showConnectionToast,showUploadToast,showInfoToast, andshowErrorToast). - Added the original button click sound to the Slim Model toggle switch.
### Changed
- Redesigned the client Settings screen: replaced the dropdown menu with search-filterable and collapsible accordion categories.
- Replaced the library slot thumbnail rendering with a 2D player face (matching the Tab Server List appearance) utilizing
PlayerFaceExtractorto integrate with Minecraft's deferred PiP rendering pipeline. - Shortened Toast messages in English and Thai language files to prevent text overflowing the toast boxes.
### Fixed
- Decoupled connection checks from skin downloads: increased client concurrent connection limit to 50 and executed pings on a separate thread pool to ensure player skins load instantly without queueing.
- Fixed the "Clear Skin" action: attached the Mojang verification session token to clear selection requests to prevent HTTP 401 Unauthorized errors on session-enforced servers.
- Fixed skin texture registration issues by utilizing a 2-argument
ResourceTextureconstructor to prevent path modification.
### Added
- Added editable
catskinCloudIpsetting to specify custom server addresses. The server URL is automatically normalized and prepended with a protocol (http://orhttps://) if missing. - Added toggle settings to selectively enable or disable various toast notifications (
showConnectionToast,showUploadToast,showInfoToast, andshowErrorToast). - Added the original button click sound to the Slim Model toggle switch.
### Changed
- Redesigned the client Settings screen: replaced the dropdown menu with search-filterable and collapsible accordion categories.
### Fixed
- Decoupled connection checks from skin downloads: increased client concurrent connection limit to 50 and executed pings on a separate thread pool to ensure player skins load instantly without queueing.
- Fixed the "Clear Skin" action: attached the Mojang verification session token to clear selection requests to prevent HTTP 401 Unauthorized errors on session-enforced servers.
### Added
- Added editable
catskinCloudIpsetting to specify custom server addresses. The server URL is automatically normalized and prepended with a protocol (http://orhttps://) if missing. - Added toggle settings to selectively enable or disable various toast notifications (
showConnectionToast,showUploadToast,showInfoToast, andshowErrorToast). - Added the original button click sound to the Slim Model toggle switch.
### Changed
- Redesigned the client Settings screen: replaced the dropdown menu with search-filterable and collapsible accordion categories.
### Fixed
- Decoupled connection checks from skin downloads: increased client concurrent connection limit to 50 and executed pings on a separate thread pool to ensure player skins load instantly without queueing.
- Fixed the "Clear Skin" action: attached the Mojang verification session token to clear selection requests to prevent HTTP 401 Unauthorized errors on session-enforced servers.
### Added
- Added editable
catskinCloudIpsetting to specify custom server addresses. The server URL is automatically normalized and prepended with a protocol (http://orhttps://) if missing. - Added toggle settings to selectively enable or disable various toast notifications (
showConnectionToast,showUploadToast,showInfoToast, andshowErrorToast). - Added the original button click sound to the Slim Model toggle switch.
### Changed
- Redesigned the client Settings screen: replaced the dropdown menu with search-filterable and collapsible accordion categories.
### Fixed
- Decoupled connection checks from skin downloads: increased client concurrent connection limit to 50 and executed pings on a separate thread pool to ensure player skins load instantly without queueing.
- Fixed the "Clear Skin" action: attached the Mojang verification session token to clear selection requests to prevent HTTP 401 Unauthorized errors on session-enforced servers.
### Added
- Added editable
catskinCloudIpsetting to specify custom server addresses. The server URL is automatically normalized and prepended with a protocol (http://orhttps://) if missing. - Added toggle settings to selectively enable or disable various toast notifications (
showConnectionToast,showUploadToast,showInfoToast, andshowErrorToast). - Added the original button click sound to the Slim Model toggle switch.
### Changed
- Redesigned the client Settings screen: replaced the dropdown menu with search-filterable and collapsible accordion categories.
### Fixed
- Decoupled connection checks from skin downloads: increased client concurrent connection limit to 50 and executed pings on a separate thread pool to ensure player skins load instantly without queueing.
- Fixed the "Clear Skin" action: attached the Mojang verification session token to clear selection requests to prevent HTTP 401 Unauthorized errors on session-enforced servers.
### Fixed
- Fixed a crash on launch on Fabric (
NoClassDefFoundError:
was packaged without the Minecraft name → intermediary remap, so every Minecraft
reference used development (Mojmap) names that do not exist at runtime and the
mod failed to initialize. 3.0.3-HF is rebuilt with the remap correctly applied.
This is a packaging fix only — there are no gameplay or code changes versus
3.0.3, and the Figura compatibility fix from 3.0.3 is included. (NeoForge runs
with Mojang-mapped names at runtime and was not affected.)
- Figura compatibility: CatSkinC now yields to an active Figura avatar. When a
that player so the two mods no longer compete over the same skin lookups.
Detection is reflective and Figura remains an optional dependency. (1.20.1
already overrides texture and model through separate methods and did not show
the 1.21.1
getSkin() conflict; this keeps behaviour consistent andfuture-proof.)
### Fixed
- Figura compatibility: CatSkinC now yields to an active Figura avatar. When a
that player so the two mods no longer compete over the same skin lookups.
Detection is reflective and Figura remains an optional dependency. (1.20.1
already overrides texture and model through separate methods and did not show
the 1.21.1
getSkin() conflict; this keeps behaviour consistent andfuture-proof.)
### Fixed
- Figura compatibility: CatSkinC now yields to an active Figura avatar. When a
that player so the two mods no longer compete over the same skin lookups.
Detection is reflective and Figura remains an optional dependency. (1.20.1
already overrides texture and model through separate methods and did not show
the 1.21.1
getSkin() conflict; this keeps behaviour consistent andfuture-proof.)
### Fixed
- Figura compatibility: CatSkinC now yields to an active Figura avatar. When a
that player so the two mods no longer compete over the same skin lookups.
Detection is reflective and Figura remains an optional dependency. (1.20.1
already overrides texture and model through separate methods and did not show
the 1.21.1
getSkin() conflict; this keeps behaviour consistent andfuture-proof.)
### Added
- Auto-update now resolves the exact download for your platform: when a newer
loader and Minecraft version and surfaces the matching file (falling back to
the project page when no direct file matches).
### Changed
- Upload errors caused by session/identity checks now show clear, actionable
server text.
### Fixed
- Mouth PNGs that do not match the base skin size are now rejected up front with
- Fixed a native-image leak and double-free on the skin texture apply error path.
### Added
- Auto-update now resolves the exact download for your platform: when a newer
loader and Minecraft version and surfaces the matching file (falling back to
the project page when no direct file matches).
### Changed
- Upload errors caused by session/identity checks now show clear, actionable
server text.
### Fixed
- Mouth PNGs that do not match the base skin size are now rejected up front with
- Fixed a native-image leak and double-free on the skin texture apply error path.
### Added
- Auto-update now resolves the exact download for your platform: when a newer
loader and Minecraft version and surfaces the matching file (falling back to
the project page when no direct file matches).
### Changed
- Upload errors caused by session/identity checks now show clear, actionable
server text.
### Fixed
- Mouth PNGs that do not match the base skin size are now rejected up front with
- Fixed a native-image leak and double-free on the skin texture apply error path.
### Added
- Auto-update now resolves the exact download for your platform: when a newer
loader and Minecraft version and surfaces the matching file (falling back to
the project page when no direct file matches).
### Changed
- Upload errors caused by session/identity checks now show clear, actionable
server text.
### Fixed
- Mouth PNGs that do not match the base skin size are now rejected up front with
- Fixed a native-image leak and double-free on the skin texture apply error path.
- Add 3D display head
- Add 3D display head