COWMODSКаталог модов

CatSkinC

A simple skin mod for use in other server and make your skin can use with high resolution up to 8192x!

14,4 тыс.16обновлён 2 окт. 2026 г.
ДекорУправлениеОбщение

Описание

🐾CatSkinC – Easy Minecraft Skin Manager

Modrinth CurseForge Downloads Discord

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.


Upload example


✨ Features

  • 🎨 In-game skin upload — press K to 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

  1. Install the mod on your client (and any friends who want to see custom skins).
  2. Join any world or server.
  3. Press K, drag in a PNG skin (64×64 or higher, square, power-of-two).
  4. (Optional) Add mouth-open / mouth-close overlays for the talking effect.
  5. 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
AccountPremium / Mojang account (offline/cracked uploads are rejected)

Supported versions & loaders

MinecraftLoaders
1.21.1Fabric, NeoForge
1.20.1Fabric, 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:


📜 License

GPL-3.0-or-later.

Made by Cat Lab_ 9Creations Club (Q Team Studio).

Галерея

Normal Mojang skin.Use CatSkinC.UI

Последние версии

Все версии →
release

CatSkinC 4.1.0 (NeoForge)

4.1.0+neoforge
2 окт. 2026 г.107Minecraft: 1.21.1neoforge
Скачать
Что нового
### Fixed - Skin update events now bypass the short-lived selected-skin cache, so changed skins are fetched immediately instead of waiting for the cache to expire. - Force-refresh events received during an active fetch are coalesced into a follow-up fetch; late responses can no longer restore stale cached selections.
release

CatSkinC 4.1.0 (Fabric)

4.1.0+fabric
2 окт. 2026 г.195Minecraft: 1.21.1fabric
Скачать
Что нового
### Fixed - Skin update events now bypass the short-lived selected-skin cache, so changed skins are fetched immediately instead of waiting for the cache to expire. - Force-refresh events received during an active fetch are coalesced into a follow-up fetch; late responses can no longer restore stale cached selections.
release

CatSkinC 4.1.0 (Forge)

4.1.0+forge
2 окт. 2026 г.375Minecraft: 1.20.1forge
Скачать
Что нового
### Fixed - Skin update events now bypass the short-lived selected-skin cache, so changed skins are fetched immediately instead of waiting for the cache to expire. - Force-refresh events received during an active fetch are coalesced into a follow-up fetch; late responses can no longer restore stale cached selections.
release

CatSkinC 4.1.0 (Fabric)

4.1.0+fabric
2 окт. 2026 г.181Minecraft: 1.20.1fabric
Скачать
Что нового
### Fixed - Skin update events now bypass the short-lived selected-skin cache, so changed skins are fetched immediately instead of waiting for the cache to expire. - Force-refresh events received during an active fetch are coalesced into a follow-up fetch; late responses can no longer restore stale cached selections.
release

CatSkinC 4.0.1 (NeoForge)

4.0.1+neoforge
25 сент. 2026 г.50Minecraft: 1.21.1neoforge
Скачать
Что нового
### Fixed - 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.
release

CatSkinC 4.0.1 (Fabric)

4.0.1+fabric
25 сент. 2026 г.57Minecraft: 1.21.1fabric
Скачать
Что нового
### Fixed - 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.
release

CatSkinC 4.0.0 (NeoForge)

4.0.0+neoforge
17 сент. 2026 г.38Minecraft: 1.21.1neoforge
Скачать
Что нового
### Added - **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: 3` header 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 players use lazily cached, pixel-perfect half, quarter, or eighth-resolution 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 control, Normal and Panicked modes, and links to Minecraft's keybinding menu. - Default keybindings for increasing and decreasing the Myopia range with the Up and Down arrow keys. All settings are persisted in `catskinc.json`. ### Changed - **Join flow** now attempts WebSocket first, falls back to SSE on failure. - **Shared circuit breaker state** between `ServerApiClient` and `WebSocketClient` — 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-Protocol` to WebSocket upgrade request. - **Auth race** — session token acquired synchronously before WebSocket connection attempt. - **Protocol defense** — client verifies `protocol_version` in 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 chains `thenRun(refresh)` so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - **Pending selections cache**: `PENDING_SELECTIONS` returns 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_CACHE` on 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 `circuitOpenUntilMs` before connecting, eliminating useless retries during outage. - **AtomicInteger**: `consecutiveFailures` switched to `AtomicInteger` for 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's `requestSigningKey`. This matches the server's `verify_download_signature()` check when `ENFORCE_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`. Downloaded `NativeImage` objects are cached and pixel-copied into one shared `catskinc:dynamic/active` texture 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 in `build.gradle` to 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.
release

CatSkinC 4.0.0 (Fabric)

4.0.0+fabric
17 сент. 2026 г.62Minecraft: 1.21.1fabric
Скачать
Что нового
### Added - **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: 3` header 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 players use lazily cached, pixel-perfect half, quarter, or eighth-resolution 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 control, Normal and Panicked modes, and links to Minecraft's keybinding menu. - Default keybindings for increasing and decreasing the Myopia range with the Up and Down arrow keys. All settings are persisted in `catskinc.json`. ### Changed - **Join flow** now attempts WebSocket first, falls back to SSE on failure. - **Shared circuit breaker state** between `ServerApiClient` and `WebSocketClient` — 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-Protocol` to WebSocket upgrade request. - **Auth race** — session token acquired synchronously before WebSocket connection attempt. - **Protocol defense** — client verifies `protocol_version` in 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 chains `thenRun(refresh)` so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - **Pending selections cache**: `PENDING_SELECTIONS` returns 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_CACHE` on 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 `circuitOpenUntilMs` before connecting, eliminating useless retries during outage. - **AtomicInteger**: `consecutiveFailures` switched to `AtomicInteger` for 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's `requestSigningKey`. This matches the server's `verify_download_signature()` check when `ENFORCE_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`. Downloaded `NativeImage` objects are cached and pixel-copied into one shared `catskinc:dynamic/active` texture 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 in `build.gradle` to 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.
release

CatSkinC 4.0.0 (Forge)

4.0.0+forge
17 сент. 2026 г.186Minecraft: 1.20.1forge
Скачать
Что нового
### Added - **Myopia skin LOD** for CatSkinC-managed remote skins. When enabled, distant players use lazily cached, pixel-perfect half, quarter, or eighth-resolution 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 control, Normal and Panicked modes, and links to Minecraft's keybinding menu. - Default keybindings for increasing and decreasing the Myopia range with the Up and Down arrow keys. All settings are persisted in `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: 3` header 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 `ServerApiClient` and `WebSocketClient` — 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 textures and resets per-player LOD state. ### Fixed - **Broadcast framing** — WebSocket clients now receive raw JSON (SSE `data: ` prefix stripped server-side). - **Handshake protocol header** — added `X-CatSkinC-Protocol` to WebSocket upgrade request. - **Auth race** — session token acquired synchronously before WebSocket connection attempt. - **Protocol defense** — client verifies `protocol_version` in 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 chains `thenRun(refresh)` so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - **Pending selections cache**: `PENDING_SELECTIONS` returns 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_CACHE` on 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 `circuitOpenUntilMs` before connecting, eliminating useless retries during outage. - **AtomicInteger**: `consecutiveFailures` switched to `AtomicInteger` for 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's `requestSigningKey`. This matches the server's `verify_download_signature()` check when `ENFORCE_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 vanilla `TextureManager`. Instead, downloaded `NativeImage` objects are cached in `SKIN_IMAGES` and pixel-copied into one shared `catskinc:dynamic/active` texture 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-Protocol` to WebSocket upgrade request. - **Auth race** — session token acquired synchronously before WebSocket connection attempt. - **Protocol defense** — client verifies `protocol_version` in 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 chains `thenRun(refresh)` so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - **Pending selections cache**: `PENDING_SELECTIONS` returns 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_CACHE` on 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 `circuitOpenUntilMs` before connecting, eliminating useless retries during outage. - **AtomicInteger**: `consecutiveFailures` switched to `AtomicInteger` for 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's `requestSigningKey`. This matches the server's `verify_download_signature()` check when `ENFORCE_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 vanilla `TextureManager`. Instead, downloaded `NativeImage` objects are cached in `SKIN_IMAGES` and pixel-copied into one shared `catskinc:dynamic/active` texture 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 in `build.gradle` to 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.
release

CatSkinC 4.0.0 (Fabric)

4.0.0+fabric
17 сент. 2026 г.77Minecraft: 1.20.1fabric
Скачать
Что нового
### Added - **Myopia skin LOD** for CatSkinC-managed remote skins. When enabled, distant players use lazily cached, pixel-perfect half, quarter, or eighth-resolution 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 control, Normal and Panicked modes, and links to Minecraft's keybinding menu. - Default keybindings for increasing and decreasing the Myopia range with the Up and Down arrow keys. All settings are persisted in `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: 3` header 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 `ServerApiClient` and `WebSocketClient` — 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 textures and resets per-player LOD state. ### Fixed - **Broadcast framing** — WebSocket clients now receive raw JSON (SSE `data: ` prefix stripped server-side). - **Handshake protocol header** — added `X-CatSkinC-Protocol` to WebSocket upgrade request. - **Auth race** — session token acquired synchronously before WebSocket connection attempt. - **Protocol defense** — client verifies `protocol_version` in 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 chains `thenRun(refresh)` so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - **Pending selections cache**: `PENDING_SELECTIONS` returns 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_CACHE` on 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 `circuitOpenUntilMs` before connecting, eliminating useless retries during outage. - **AtomicInteger**: `consecutiveFailures` switched to `AtomicInteger` for 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's `requestSigningKey`. This matches the server's `verify_download_signature()` check when `ENFORCE_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 vanilla `TextureManager`. Instead, downloaded `NativeImage` objects are cached in `SKIN_IMAGES` and pixel-copied into one shared `catskinc:dynamic/active` texture 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-Protocol` to WebSocket upgrade request. - **Auth race** — session token acquired synchronously before WebSocket connection attempt. - **Protocol defense** — client verifies `protocol_version` in 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 chains `thenRun(refresh)` so the POST completes before the GET, eliminating the 4-8s skin delay after upload. - **Pending selections cache**: `PENDING_SELECTIONS` returns 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_CACHE` on 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 `circuitOpenUntilMs` before connecting, eliminating useless retries during outage. - **AtomicInteger**: `consecutiveFailures` switched to `AtomicInteger` for 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's `requestSigningKey`. This matches the server's `verify_download_signature()` check when `ENFORCE_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 vanilla `TextureManager`. Instead, downloaded `NativeImage` objects are cached in `SKIN_IMAGES` and pixel-copied into one shared `catskinc:dynamic/active` texture 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 in `build.gradle` to 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.