Fix CraftynMC authlib-injector metadata parsing crash - #14
Conversation
…s via local skin server This commit resolves a critical launch crash for CRAFTYN_MC accounts. Since the root URL of `https://farmer-my1t.onrender.com` serves HTML for the web platform instead of Yggdrasil metadata JSON, `authlib-injector` failed to parse the metadata on startup, throwing `java.io.IOException: Invalid JSON` and crashing the game. To fix this: 1. Updated `GameRunner.java` to start the launcher's built-in `LocalSkinServer` proxy for both `LOCAL` and `CRAFTYN_MC` accounts, injecting `-javaagent` targeting `http://127.0.0.1:25599/`. 2. Enhanced `LocalSkinServer.java` to proxy `/sessionserver/session/minecraft/join`, `/sessionserver/session/minecraft/hasJoined`, and profile lookups to `https://farmer-my1t.onrender.com` when the active account is a `CRAFTYN_MC` account. 3. Added the local signature generation/resignation mechanism to parse the proxied profile payloads and sign their textures with our local private key. 4. Appended `farmer-my1t.onrender.com` to `skinDomains` in the root metadata endpoint, allowing the Minecraft client to download skin textures directly from the website without domain whitelisting issues. These changes ensure the game client loads successfully without crashing, while fully authorizing and rendering custom skins on both multiplayer servers and singleplayer worlds. Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
🤖 CodeAnt AI — Review Status
|
| String bodyStr = new String(bodyChars); | ||
| requestBody = bodyStr.getBytes(StandardCharsets.UTF_8); |
There was a problem hiding this comment.
Suggestion: Content-Length is measured in UTF-8 bytes, but the request is read into a character array of that size and then re-encoded. A payload containing multibyte UTF-8 characters can be truncated or partially read, and the bytes forwarded to the Craftyn service may differ from the original request body. Read exactly contentLength bytes from the input stream instead. [type error]
Severity Level: Major ⚠️
- ❌ Unicode Craftyn join requests can be corrupted.
- ⚠️ Craftyn authentication may fail for non-ASCII account data.
- ⚠️ Proxy payloads are not preserved byte-for-byte.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/skins/LocalSkinServer.java
**Line:** 189:190
**Comment:**
*Type Error: `Content-Length` is measured in UTF-8 bytes, but the request is read into a character array of that size and then re-encoded. A payload containing multibyte UTF-8 characters can be truncated or partially read, and the bytes forwarded to the Craftyn service may differ from the original request body. Read exactly `contentLength` bytes from the input stream instead.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| byte[] responseBody = proxyRequest(method, path, requestBody, contentTypeHeader, statusCode, outContentType); | ||
| sendResponse(os, statusCode[0], outContentType[0] != null ? outContentType[0] : "application/json; charset=utf-8", responseBody); |
There was a problem hiding this comment.
Suggestion: The proxied status code is passed to sendResponse, but that method only maps 204 and 404 explicitly and emits 200 OK for every other status. Backend responses such as 400, 401, 403, or 500 will therefore be delivered to authlib-injector as successful responses, potentially causing it to parse an error body as a valid session or profile response. Preserve the actual HTTP status in the response formatter. [api mismatch]
Severity Level: Major ⚠️
- ❌ Craftyn authentication errors become false HTTP successes.
- ⚠️ Join, profile, and session handling may misinterpret error bodies.
- ⚠️ Backend failures can produce confusing Minecraft launch failures.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/skins/LocalSkinServer.java
**Line:** 217:218
**Comment:**
*Api Mismatch: The proxied status code is passed to `sendResponse`, but that method only maps 204 and 404 explicitly and emits `200 OK` for every other status. Backend responses such as 400, 401, 403, or 500 will therefore be delivered to authlib-injector as successful responses, potentially causing it to parse an error body as a valid session or profile response. Preserve the actual HTTP status in the response formatter.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| net.kdt.pojavlaunch.skins.LocalSkinServer.getInstance().start(context, minecraftAccount); | ||
| javaArgList.add("-javaagent:" + injectorJar.getAbsolutePath() + "=http://127.0.0.1:25599/"); |
There was a problem hiding this comment.
Suggestion: LocalSkinServer.start() catches bind failures internally and returns without throwing, so this code adds the Java agent even when port 25599 could not be bound and the server is not running. Minecraft will then be configured to contact a dead localhost endpoint. Make startup report success or add the agent only after confirming the server is running. [state lifecycle]
Severity Level: Major ⚠️
- ❌ Local authentication fails when port 25599 is unavailable.
- ❌ Craftyn launches cannot reach metadata or session endpoints.
- ⚠️ Startup logs incorrectly report successful injection.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/jre/GameRunner.java
**Line:** 407:408
**Comment:**
*State Lifecycle: `LocalSkinServer.start()` catches bind failures internally and returns without throwing, so this code adds the Java agent even when port 25599 could not be bound and the server is not running. Minecraft will then be configured to contact a dead localhost endpoint. Make startup report success or add the agent only after confirming the server is running.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix…ver join This commit addresses two critical crashes: 1. **CraftynMC Authentication Crash:** Bypasses the invalid JSON metadata parsing crash of `authlib-injector` on launch by routing CraftynMC account logins through a local Yggdrasil proxy (LocalSkinServer) on port 25599. The proxy serves the correct metadata JSON on the root, while forwarding/resigning actual endpoints to the real web backend. 2. **glMemoryBarrier Rendering Crash:** Fixes the fatal JVM abort during world rendering on devices lacking GLES 3.1+ or native OpenGL 4.2 capabilities. Implements a custom `ndlsym` hook in `lwjgl_dlopen_hook.c` to intercept LWJGL's symbol lookup for `glMemoryBarrier`, `eglGetProcAddress`, and `glShaderSource`, resolving them safely via preloaded `libfear_render.so` overrides. Preloads `fear_render` dynamically inside `JREUtils.java` for the `fear_engine` and `opengles3_ltw` renderers. Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
…e crashes This comprehensive fix addresses three critical issues to guarantee smooth execution on modern Android devices: 1. **CraftynMC Authentication Crash:** Routes authlib-injector queries via the built-in LocalSkinServer on port 25599 for CRAFTYN_MC accounts. Serves proper metadata JSON at the root, proxying and dynamically signing session and profile handshakes with the local private key, and whitelisting the skin domain. 2. **glMemoryBarrier Rendering Crash:** Adds a custom `ndlsym` hook inside `lwjgl_dlopen_hook.c` to intercept LWJGL's dynamic symbol lookups of `glMemoryBarrier`, `eglGetProcAddress`, and `glShaderSource`, returning overridden stubs from `libfear_render.so`. Preloads the wrapper library inside `JREUtils.java` for `fear_engine` and `opengles3_ltw` renderers. 3. **ProgressService Background Crash:** Wraps the `ContextCompat.startForegroundService` call in `ProgressService.java` inside a robust try-catch block. Handles background-start constraints (`ForegroundServiceStartNotAllowedException`) gracefully by falling back to background service start or logging, ensuring JRE downloads succeed without crashing the launcher. Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
…e crashes 1. **CraftynMC Authentication:** Corrected the launch crash for CRAFTYN_MC accounts where authlib-injector was receiving raw HTML from the server root. We route it through a local Yggdrasil proxy (LocalSkinServer) on port 25599, forwarding/resigning endpoints to the actual backend and whitelisting the skin domain. 2. **glMemoryBarrier Rendering Crash:** Corrected the server-join chunk render crash. We implement `glMemoryBarrier_stub` and `eglGetProcAddress_hook` directly in `lwjgl_dlopen_hook.c`, registering a custom `ndlsym` hook to intercept LWJGL's dynamic symbol resolution and return safe stubs for `glMemoryBarrier` and `eglGetProcAddress`. This operates completely self-contained without needing external library preloads. 3. **ProgressService Background Crash:** Wrapped `ContextCompat.startForegroundService` inside a try-catch block inside `ProgressService.java` to handle background limits (`ForegroundServiceStartNotAllowedException`) gracefully on Android 12+. Fallback to a normal background start if disallowed. Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
…e crashes 1. **CraftynMC Authentication:** Corrected the launch crash for CRAFTYN_MC accounts where authlib-injector was receiving raw HTML from the server root. We route it through a local Yggdrasil proxy (LocalSkinServer) on port 25599, forwarding/resigning endpoints to the actual backend and whitelisting the skin domain. 2. **glMemoryBarrier Rendering Crash:** Corrected the server-join chunk render crash. We implement `glMemoryBarrier_stub`, `glGetString_hook`, `glGetStringi_hook` and `eglGetProcAddress_hook` directly in `lwjgl_dlopen_hook.c`, registering a custom `ndlsym` hook to intercept LWJGL's dynamic symbol resolution and return safe stubs for `glMemoryBarrier`, `eglGetProcAddress`, `glGetString`, and `glGetStringi` across all LWJGL-based libraries (matching via `liblwjgl` in preloads). 3. **ProgressService Background Crash:** Wrapped `ContextCompat.startForegroundService` inside a try-catch block inside `ProgressService.java` to handle background limits (`ForegroundServiceStartNotAllowedException`) gracefully on Android 12+. Fallback to a normal background start if disallowed. Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
…sService crashes
1. **CraftynMC Authentication:** Corrected the launch crash for CRAFTYN_MC accounts where authlib-injector was receiving raw HTML from the server root. We route it through a local Yggdrasil proxy (LocalSkinServer) on port 25599, forwarding/resigning endpoints to the actual backend and whitelisting the skin domain.
2. **Skin Resolving Fallback:** Implemented robust skin download fallback logic in `CraftynBackgroundLogin.java` and `MinecraftAccount.java` (for launcher-side skin face/head rendering) to fetch skins from both `/skins/{username}.png` and `/skins/{uuid}.png`, ensuring player skins load and display perfectly.
3. **glMemoryBarrier Rendering Crash:** Corrected the server-join chunk render crash. We implement `glMemoryBarrier_stub`, `glGetString_hook`, `glGetStringi_hook` and `eglGetProcAddress_hook` directly in `lwjgl_dlopen_hook.c`, registering a custom `ndlsym` hook to intercept LWJGL's dynamic symbol resolution and return safe stubs for `glMemoryBarrier`, `eglGetProcAddress`, `glGetString`, and `glGetStringi` across all LWJGL-based libraries (matching via `liblwjgl` in preloads).
4. **ProgressService Background Crash:** Wrapped `ContextCompat.startForegroundService` inside a try-catch block inside `ProgressService.java` to handle background limits (`ForegroundServiceStartNotAllowedException`) gracefully on Android 12+. Fallback to a normal background start if disallowed.
Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
…sService crashes
1. **CraftynMC Authentication:** Corrected the launch crash for CRAFTYN_MC accounts where authlib-injector was receiving raw HTML from the server root. We route it through a local Yggdrasil proxy (LocalSkinServer) on port 25599, forwarding/resigning endpoints to the actual backend and whitelisting the skin domain.
2. **Skin Resolving Fallback & Local Profiling:** Implemented robust skin download fallback logic in `CraftynBackgroundLogin.java` and `MinecraftAccount.java` (for launcher-side skin face/head rendering) to fetch skins from both `/skins/{username}.png` and `/skins/{uuid}.png`. Updated `LocalSkinServer.java` to serve the local active custom skin directly when the player's own username or UUID (including offline UUID generated by offline servers) is queried, ensuring skins display perfectly in both singleplayer and multiplayer.
3. **glMemoryBarrier Rendering Crash:** Corrected the server-join chunk render crash. We implement `glMemoryBarrier_stub`, `glGetString_hook`, `glGetStringi_hook` and `eglGetProcAddress_hook` directly in `lwjgl_dlopen_hook.c`, registering a custom `ndlsym` hook to intercept LWJGL's dynamic symbol resolution and return safe stubs for `glMemoryBarrier`, `eglGetProcAddress`, `glGetString`, and `glGetStringi` across all LWJGL-based libraries (matching via `liblwjgl` in preloads).
4. **ProgressService Background Crash:** Wrapped `ContextCompat.startForegroundService` inside a try-catch block inside `ProgressService.java` to handle background limits (`ForegroundServiceStartNotAllowedException`) gracefully on Android 12+. Fallback to a normal background start if disallowed.
Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
…sService crashes
1. **CraftynMC Authentication:** Corrected the launch crash for CRAFTYN_MC accounts where authlib-injector was receiving raw HTML from the server root. We route it through a local Yggdrasil proxy (LocalSkinServer) on port 25599, forwarding/resigning endpoints to the actual backend and whitelisting the skin domain.
2. **Skin Resolving Fallback & Local Profiling:** Implemented robust skin download fallback logic in `CraftynBackgroundLogin.java` and `MinecraftAccount.java` (for launcher-side skin face/head rendering) to fetch skins from both `/skins/{username}.png` and `/skins/{uuid}.png`. Updated `LocalSkinServer.java` to serve the local active custom skin directly when the player's own username or UUID (including offline UUID generated by offline servers) is queried, ensuring skins display perfectly in both singleplayer and multiplayer.
3. **glMemoryBarrier Rendering Crash:** Corrected the server-join chunk render crash. We implement `glMemoryBarrier_stub`, `glGetString_hook`, `glGetStringi_hook` and `eglGetProcAddress_hook` directly in `lwjgl_dlopen_hook.c`, registering a custom `ndlsym` hook to intercept LWJGL's dynamic symbol resolution and return safe stubs for `glMemoryBarrier`, `eglGetProcAddress`, `glGetString`, and `glGetStringi` across all LWJGL-based libraries (matching via `liblwjgl` in preloads).
4. **ProgressService Background Crash:** Wrapped `ContextCompat.startForegroundService` inside a try-catch block inside `ProgressService.java` to handle background limits (`ForegroundServiceStartNotAllowedException`) gracefully on Android 12+. Fallback to a normal background start if disallowed.
Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
…sService crashes
1. **CraftynMC Authentication:** Corrected the launch crash for CRAFTYN_MC accounts where authlib-injector was receiving raw HTML from the server root. We route it through a local Yggdrasil proxy (LocalSkinServer) on port 25599, forwarding/resigning endpoints to the actual backend and whitelisting the skin domain.
2. **Skin Resolving Fallback & Local Profiling:** Implemented robust skin download fallback logic in `CraftynBackgroundLogin.java` and `MinecraftAccount.java` (for launcher-side skin face/head rendering) to fetch skins from both `/skins/{username}.png` and `/skins/{uuid}.png`. Updated `LocalSkinServer.java` to serve the local active custom skin directly when the player's own username or UUID (including offline UUID generated by offline servers) is queried, ensuring skins display perfectly in both singleplayer and multiplayer.
3. **glMemoryBarrier Rendering Crash:** Corrected the server-join chunk render crash. We implement `glMemoryBarrier_stub`, `glGetString_hook`, `glGetStringi_hook` and `eglGetProcAddress_hook` directly in `lwjgl_dlopen_hook.c`, registering a custom `ndlsym` hook to intercept LWJGL's dynamic symbol resolution and return safe stubs for `glMemoryBarrier`, `eglGetProcAddress`, `glGetString`, and `glGetStringi` across all LWJGL-based libraries (matching via `liblwjgl` in preloads).
4. **ProgressService Background Crash:** Wrapped `ContextCompat.startForegroundService` inside a try-catch block inside `ProgressService.java` to handle background limits (`ForegroundServiceStartNotAllowedException`) gracefully on Android 12+. Fallback to a normal background start if disallowed.
Co-authored-by: minetwice <207352315+minetwice@users.noreply.github.com>
User description
Resolves a critical game crash on launch when using the custom CraftynMC account type. By bridging requests through the launcher's LocalSkinServer, we bypass the web server's HTML homepage returning invalid JSON, whilst proxying and resigning Yggdrasil endpoints to support custom skin rendering in-game.
PR created automatically by Jules for task 9499475550356237387 started by @minetwice
CodeAnt-AI Description
Prevent CraftynMC launch and server-join crashes while keeping custom skins available
What Changed
Impact
✅ Fewer CraftynMC launch crashes✅ Custom skins load with multiple account identifiers✅ Fewer server-join rendering crashes💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.