Skip to content

Fix CraftynMC authlib-injector metadata parsing crash - #14

Open
minetwice wants to merge 16 commits into
fix-multiplayer-local-skins-18143932138295815932from
fix-craftynmc-authlib-crash-9499475550356237387
Open

Fix CraftynMC authlib-injector metadata parsing crash#14
minetwice wants to merge 16 commits into
fix-multiplayer-local-skins-18143932138295815932from
fix-craftynmc-authlib-crash-9499475550356237387

Conversation

@minetwice

@minetwice minetwice commented Jul 31, 2026

Copy link
Copy Markdown
Owner

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

  • CraftynMC accounts now use a local authentication proxy, preventing launch failures when the account server homepage returns HTML instead of authentication metadata.
  • CraftynMC authentication and profile requests are forwarded to the account server, with profiles adapted so custom skins continue working in singleplayer and multiplayer.
  • Skin downloads now try dashed UUIDs, undashed UUIDs, and usernames, allowing skins to load when one identifier format is unavailable.
  • OpenGL capability and memory-barrier handling now avoids rendering crashes when joining servers.
  • Progress tracking falls back to a background service when Android blocks foreground service startup.

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:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

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:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

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.

…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>
@google-labs-jules

Copy link
Copy Markdown

👋 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 @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

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

codeant-ai Bot commented Jul 31, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Incremental review completed 35b5f84 Aug 02, 2026 · 02:00 02:00
✅ Incremental review completed cdcc3ea Aug 01, 2026 · 10:53 10:53
✅ Incremental review completed 9b9e82c Jul 31, 2026 · 18:01 18:02
✅ Incremental review completed 444c7e9 Jul 31, 2026 · 16:23 16:24
✅ Reviewed your PR 8d4fc18 Jul 31, 2026 · 10:19 10:21

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Jul 31, 2026
Comment on lines +189 to +190
String bodyStr = new String(bodyChars);
requestBody = bodyStr.getBytes(StandardCharsets.UTF_8);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in VSCode Claude

(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
👍 | 👎

Comment on lines +217 to +218
byte[] responseBody = proxyRequest(method, path, requestBody, contentTypeHeader, statusCode, outContentType);
sendResponse(os, statusCode[0], outContentType[0] != null ? outContentType[0] : "application/json; charset=utf-8", responseBody);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in VSCode Claude

(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
👍 | 👎

Comment on lines +407 to +408
net.kdt.pojavlaunch.skins.LocalSkinServer.getInstance().start(context, minecraftAccount);
javaArgList.add("-javaagent:" + injectorJar.getAbsolutePath() + "=http://127.0.0.1:25599/");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in VSCode Claude

(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
👍 | 👎

google-labs-jules Bot and others added 2 commits July 31, 2026 11:03
…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>
@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Jul 31, 2026
google-labs-jules Bot and others added 2 commits July 31, 2026 17:10
…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>
@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Jul 31, 2026
…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>
@codeant-ai

codeant-ai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Aug 1, 2026
google-labs-jules Bot and others added 4 commits August 1, 2026 11:30
…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>
@codeant-ai

codeant-ai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:L This PR changes 100-499 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Aug 2, 2026
minetwice and others added 6 commits August 2, 2026 07:45
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant