Tags
Creators
Details
2.17.145
Compatibility
Changes
NovaSync 2.17.145 — Mojang-route resilience + Bedrock skin path fixes
Patch series 2.17.134 → 2.17.145 shipped in one day after a Hyperlayer SA → Mojang routing degradation broke player joins. End-to-end hardening of every outbound Mojang/Microsoft/Geyser endpoint NovaSync depends on.
MojangRetryProxy (compat shim)
- Multi-host coverage now wraps every flaky Mojang/Microsoft/Geyser endpoint that affects auth, secure-profile, Bedrock discovery, OpenID issuer, profile lookup, and skin textures:
api.minecraftservices.com,*.minecraft-services.net,sessionserver.mojang.com,api.mojang.com,textures.minecraft.net,api.geysermc.org. - Per-host wildcard matching (
*.minecraft-services.net) covers the full Cloudburst discovery → issuer → jwks → token chain. - Handshake-retry:
setSoTimeout(handshakeMs)beforestartHandshake()plus a 6-attempt retry loop sharing the same budget as read-retries. JDK-clean way to interrupt a stuck TLS handshake (replaces the prior watchdog-thread approach that raced on the inner-socket field). - Install hook moved from
onEnabletoonLoadso the shim is the JVM-wide default SSLSocketFactory before authlib'sYggdrasilServicesKeyInfoclass init runs its first publickeys fetch (~5s after ServerMain). - JVM-wide
sun.net.client.defaultConnectTimeout=8000+defaultReadTimeout=10000+http.keepAlive=falseset at install (when not already operator-configured). - SEVERE log on install failure so admins see when the shim is INACTIVE.
MojangPublicKeysCache (new)
- Disk-cache for
/publickeysatplugins/NovaSyncPlugin/cache/mojang-publickeys.json. One successful fetch buys months of resilience (keys rotate rarely). - On retry exhaustion, splices a synthesized
HTTP/1.1 200 OKresponse (SequenceInputStreamof headers + body) intoRetryingSSLSocket.getInputStream()so the application-layer HTTP parser inside authlib'sMinecraftClientreads cached bytes seamlessly. - Atomic
CacheEntryrecord so body + timestamp can never tear under concurrent reads. - Strict JSON shape validation before save (requires
{...}/[...]wrapping +publicKey/BEGINsubstring + Content-Length-delimited body) — prevents a truncated upstream response from poisoning the cache for 90 days. - Async file I/O dispatched to a daemon executor so saves don't block the auth hot-path.
- Early cache fallback once two upstream retries have failed AND the cache is warm — keeps total elapsed under Paper's ~30 s login window.
- Boot-time
warmAsync()pre-fetches the cache in the background.
ConfigMigrator (Geyser auto-patch)
- New idempotent patch for
bedrock.cooldown-type: disabled. Geyser's cooldown indicator renders via a translatable component (geyser.opt.cooldown.*); when the Bedrock locale-asset cache fails to load on a degraded route, the Bedrock client cannot resolve the key and renders the rawgeyser.opt.cooldown:nonliteral as floating HUD text on every hotbar-slot change. Disabling the indicator avoids the broken-translation render.
BedrockSkinFix
is_steveboolean parsing fixed (was using the string-onlyextractJsonStringhelper, which always returned a substring of the next quoted field; the equality check never matched). NewextractJsonBooleanis whitespace-tolerant and word-boundary terminated.- Stop overriding Floodgate's textures URL when
is_steve=true. Geyser'sis_steveflag reflects the player's Xbox Live persona skin, not their currently-active local Bedrock skin (Marketplace/custom). Floodgate has already uploaded the correct visual; preserve its URL.
Cross-vendor review
Findings consolidated from DeepSeek V4-Pro + Gemini 3.1-Pro (via OpenRouter) + java-plugin-specialist agent throughout the patch series.
Tested live on Hyperlayer SA (Paper 1.21.11, Java 21, Geyser-Spigot 2.10.0, Floodgate 2.2.5).
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:h1VoTTz6:8scJlEmn"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:h1VoTTz6:8scJlEmn"
}

