Skip to content

Conversation

@emyfops
Copy link
Collaborator

@emyfops emyfops commented Feb 22, 2025

This pull request introduces a Network module which handles basic authentication against the lambda api
Additionally, players can link their discord account using the rpc to access party features
These features include:

  • Joining friends lobbies (without joining servers due to security concerns)
  • Qol features such as nametags on top of friends and those who are in the party

The commit 3a3feba was accidentally pushed on the wrong branch due to github desktop bugs, it does not show up on my machine but does on remote
This pull request is not ready to be merged

Summary by CodeRabbit

  • New Features

    • Revamped Discord integration now supports seamless account linking and enhanced party management.
    • Enhanced cape customization with a refreshed, custom cape texture and new options to set and retrieve capes.
    • Streamlined network login and authentication for a smoother connection experience.
    • Introduced a world status indicator that displays "Multiplayer", "Singleplayer", or "Main Menu" based on your current session.
    • Added functionality for fetching and managing player capes, including caching and retrieval processes.
    • New command for setting user capes via a simple command interface.
    • New methods for handling player join and leave events, enhancing multiplayer interactions.
    • Added a new property to determine the game world context based on server status.
    • New methods for modifying cape rendering based on player UUID.
    • New methods for linking Discord accounts and managing Discord presence.
    • New methods for reading images directly from byte arrays.
  • Bug Fixes

    • Improved error handling for network operations related to Discord and cape management.
  • Chores

    • Updated dependencies and package structures for better organization and maintainability.

@github-actions github-actions bot added triage Requires labelling or review 1.20 labels Feb 22, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🔭 Outside diff range comments (1)
common/src/main/kotlin/com/lambda/network/api/v1/endpoints/JoinParty.kt (1)

36-41: ⚠️ Potential issue

Add error handling for the API response.

The current implementation directly accesses the third element of the response tuple without any error handling. This could lead to runtime exceptions if the request fails.

-) =
-	Fuel.put("${apiUrl}/api/${apiVersion.value}/party/join", listOf("id" to partyId))
-		.jsonBody("""{ "id": "$partyId" }""")
-		.authentication()
-		.bearer(Network.accessToken)
-		.responseObject<Party>().third
+) {
+    require(partyId.isNotBlank()) { "Party ID cannot be empty" }
+    require(partyId.matches("[a-zA-Z0-9]+".toRegex())) { "Invalid party ID format" }
+
+    val (request, response, result) = Fuel.put("${apiUrl}/api/${apiVersion.value}/party/join")
+        .jsonBody("""{ "id": "$partyId" }""")
+        .authentication()
+        .bearer(Network.accessToken)
+        .responseObject<Party>()
+
+    return when (result) {
+        is com.github.kittinunf.result.Result.Success -> result.value
+        is com.github.kittinunf.result.Result.Failure -> {
+            val ex = result.error
+            throw IllegalStateException("Failed to join party: ${ex.message}", ex)
+        }
+    }
+}
🧹 Nitpick comments (18)
common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt (1)

164-164: Consider making the predicate parameter required.

The default value of { true } for the predicate means the listener will unsubscribe after the first event by default. This behavior might not be obvious to users and could lead to unexpected unsubscriptions.

Consider removing the default value to make the predicate parameter required:

-    noinline predicate: SafeContext.(T) -> Boolean = { true },
+    noinline predicate: SafeContext.(T) -> Boolean,
common/src/main/kotlin/com/lambda/network/api/v1/endpoints/LeaveParty.kt (1)

28-32: LGTM! Clean implementation with centralized configuration.

The function demonstrates good practices:

  • Uses centralized configuration from Network module
  • Implements proper bearer token authentication
  • Maintains type safety with Party model

Consider adding error handling.

The current implementation might benefit from explicit error handling for network failures and API errors.

Consider wrapping the response in a Result type:

-fun leaveParty() =
+fun leaveParty(): Result<Party> = runCatching {
 	Fuel.put("${apiUrl}/api/${apiVersion.value}/party/leave")
 		.authentication()
 		.bearer(Network.accessToken)
-		.responseObject<Party>().third
+		.responseObject<Party>().third.get()
+}
common/src/main/kotlin/com/lambda/network/api/v1/endpoints/LinkDiscord.kt (2)

2-2: Update the copyright year.

The copyright year is set to 2025, which is in the future. Please update it to the current year (2024) or the year when the code was created.

- * Copyright 2025 Lambda
+ * Copyright 2024 Lambda

29-33: Validate the Discord token format.

The function accepts any string as a Discord token without validation. Consider adding input validation to ensure the token matches the expected format.

 fun linkDiscord(
 	// The player's Discord token.
 	// example: OTk1MTU1NzcyMzYxMTQ2NDM4
 	discordToken: String,
-) =
+) {
+    require(discordToken.matches(Regex("^[A-Za-z0-9_-]+$"))) { "Invalid Discord token format" }
common/src/main/kotlin/com/lambda/network/api/v1/endpoints/GetParty.kt (1)

28-32: Consider handling errors more explicitly.
Currently, only the third component of the Fuel response triple is returned, which can obscure potential network, parsing, or authentication errors. Providing more explicit error handling or returning a richer result could improve debugging and resilience.

Here’s a sample refactor that captures both success and error cases:

-fun getParty() =
-    Fuel.get("${apiUrl}/api/${apiVersion.value}/party")
-        .authentication()
-        .bearer(Network.accessToken)
-        .responseObject<Party>().third
+fun getParty(): Party? {
+    val (_, _, result) = Fuel.get("${apiUrl}/api/${apiVersion.value}/party")
+        .authentication()
+        .bearer(Network.accessToken)
+        .responseObject<Party>()
+
+    return result.fold(
+        { party -> party },
+        { error ->
+            // TODO: log error or rethrow
+            null
+        }
+    )
+}

Would you like me to open a new ticket and provide a more detailed implementation for error handling and token refresh logic?

common/src/main/kotlin/com/lambda/Lambda.kt (1)

83-114: Consider adding SSE error handling and status code checks.
This block currently does not handle non-200 responses or exceptions that may occur when establishing the SSE connection. Additionally, because SSE streams can potentially stay open indefinitely, the call to latch.await() may block the thread if the server never closes the connection or fails mid-stream.

Below is an example diff to early-return on non-200 responses:

 client.sendAsync(request, HttpResponse.BodyHandlers.ofLines())
     .thenAccept { response ->
+        if (response.statusCode() != 200) {
+            LOG.error("SSE responded with status code: ${response.statusCode()}")
+            latch.countDown()
+            return@thenAccept
+        }
         println("Connected to SSE stream")
         response.body().forEach { line ->
             if (line.startsWith("data:")) {
                 val data = line.substring(5).trim()
                 println("Received event data: $data")
             }
         }
         latch.countDown()
     }
common/src/main/kotlin/com/lambda/network/api/v1/endpoints/PartyUpdates.kt (1)

1-47: Introduce better error handling for SSE and JSON parsing.
Currently, if the server responds with a non-200 status code or sends malformed JSON, the function may fail silently or terminate due to an unhandled exception in Lambda.gson.fromJson(...). Consider verifying the response status code and surrounding the JSON parsing with a try/catch block to mitigate unhandled exceptions.

Example snippet to handle non-200 statuses and catch JSON parse errors:

 .thenAccept { response ->
+    if (response.statusCode() != 200) {
+        Lambda.LOG.error("SSE responded with status code: ${response.statusCode()}")
+        return@thenAccept
+    }
     response.body().forEach {
         if (!it.startsWith("data:")) return@forEach
         val data = it.substring(5).trim()
+        try {
             val party = Lambda.gson.fromJson(data, Party::class.java)
             block(party)
+        } catch (e: Exception) {
+            Lambda.LOG.error("Failed to parse SSE data: $data", e)
+        }
     }
 }
common/src/main/kotlin/com/lambda/network/api/v1/endpoints/JoinParty.kt (2)

23-24: Remove duplicate import for jsonBody.

There are two imports for jsonBody. Since you're using the JSON string version in the code, you can remove the Gson-specific import:

 import com.github.kittinunf.fuel.core.extensions.jsonBody
-import com.github.kittinunf.fuel.gson.jsonBody

36-38: Avoid sending duplicate data in query params and request body.

The party ID is being sent both as a query parameter and in the request body. Choose one method, preferably the request body for POST/PUT requests.

-	Fuel.put("${apiUrl}/api/${apiVersion.value}/party/join", listOf("id" to partyId))
-		.jsonBody("""{ "id": "$partyId" }""")
+	Fuel.put("${apiUrl}/api/${apiVersion.value}/party/join")
+		.jsonBody("""{ "id": "$partyId" }""")
common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (2)

55-57: Consider secure storage or caching for apiAuth.
Storing the authentication object in memory can be risky if it persists for long sessions. Additionally, the TODO: Cache comment indicates there are plans for a more robust solution. Consider implementing secure storage or encryption to preserve user credentials.


92-107: Handle connection failures gracefully.
The call to ClientConnection.connect(addr, ...) followed by syncUninterruptibly() blocks until completion. If it fails, the user might be stuck or experience a crash. Implement error handling or fallback logic to manage unreachable servers or connection timeouts.

common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (2)

120-128: Add user feedback for successful party join.
When joining a party is successful, consider providing some positive confirmation (e.g., “You joined the party!”). This helps confirm that everything worked.


195-214: Consider dynamic button usage or fallback.
When no party is available, a "Download" button is displayed. If the user already has the client installed, they might not need this link each time. Consider tailoring the fallback button or providing a different action to improve user experience.

common/src/main/kotlin/com/lambda/network/api/v1/endpoints/Login.kt (1)

27-35: Documentation could be enhanced with response details.

While the parameter documentation is good, it would be helpful to include:

  • Expected response format
  • Possible error scenarios
  • Rate limiting details if any
common/src/main/java/com/lambda/mixin/network/ClientPlayNetworkHandlerMixin.java (1)

34-37: Consider validating packet data before posting event.

The event is posted without validating the packet data. While this might be acceptable for join events, consider adding basic validation or error handling to prevent potential issues.

 @Inject(method = "onGameJoin(Lnet/minecraft/network/packet/s2c/play/GameJoinS2CPacket;)V", at = @At("TAIL"))
 void injectJoinPacket(GameJoinS2CPacket packet, CallbackInfo ci) {
+    if (packet == null) return;
     EventFlow.post(new WorldEvent.Join());
 }
common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt (1)

39-41: Simplify class declaration and document event placement.

  1. The empty constructor can be simplified.
  2. The TODO comment suggests uncertainty about event placement. Consider moving this event to a more specific event class like ConnectionEvent or PlayerEvent if it's more appropriate.
-    class Join() : Event
+    object Join : Event
🧰 Tools
🪛 detekt (1.23.7)

[warning] 41-41: An empty default constructor can be removed.

(detekt.empty-blocks.EmptyDefaultConstructor)

common/src/main/kotlin/com/lambda/util/extension/Structures.kt (1)

192-205: Optimize bit manipulation logic for better readability and performance.

The bit manipulation logic is complex and could be refactored for better readability and performance.

Consider extracting the bit manipulation logic into a separate function:

+private fun extractStateId(palette: LongArray, index: Int, bits: Int, maxEntryValue: Long): Long {
+    val startOffset = index * bits
+    val startArrIndex = startOffset / 64
+    val endArrIndex = ((index + 1) * bits - 1) / 64
+    val startBitOffset = startOffset % 64
+
+    return if (startArrIndex == endArrIndex) {
+        palette[startArrIndex] ushr startBitOffset and maxEntryValue
+    } else {
+        (palette[startArrIndex] ushr startBitOffset or 
+         palette[endArrIndex] shl (64 - startBitOffset)) and maxEntryValue
+    }
+}

-val startOffset = index * bits
-val startArrIndex = startOffset / 64
-val endArrIndex = ((index + 1) * bits - 1) / 64
-val startBitOffset = startOffset % 64
-
-val stateId =
-    if (startArrIndex == endArrIndex) palette[startArrIndex] ushr startBitOffset and maxEntryValue
-    else (palette[startArrIndex] ushr startBitOffset or palette[endArrIndex] shl (64 - startBitOffset)) and maxEntryValue
+val stateId = extractStateId(palette, index, bits, maxEntryValue)
common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt (1)

193-208: Add error handling and cancellation support for coroutines.

While the coroutine support is a good addition, consider adding error handling and cancellation support.

Consider this implementation:

 val listener = UnsafeListener<T>(priority, this, alwaysListen) { event ->
-    runConcurrent(scheduler) {
-        function(event)
-    }
+    runConcurrent(scheduler) {
+        try {
+            function(event)
+        } catch (e: CancellationException) {
+            // Handle cancellation if needed
+            throw e
+        } catch (e: Exception) {
+            // Log or handle other exceptions
+            // Consider whether to rethrow or suppress
+        }
+    }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bfeab0 and cfa2e3f.

📒 Files selected for processing (31)
  • build.gradle.kts (2 hunks)
  • common/src/main/java/com/lambda/mixin/network/ClientPlayNetworkHandlerMixin.java (2 hunks)
  • common/src/main/java/com/lambda/mixin/world/ClientWorldMixin.java (2 hunks)
  • common/src/main/kotlin/com/lambda/Lambda.kt (5 hunks)
  • common/src/main/kotlin/com/lambda/command/commands/DiscordCommand.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/command/commands/RpcCommand.kt (0 hunks)
  • common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt (3 hunks)
  • common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt (3 hunks)
  • common/src/main/kotlin/com/lambda/http/api/rpc/v1/endpoints/UpdateParty.kt (0 hunks)
  • common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/module/modules/client/DiscordRPC.kt (0 hunks)
  • common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/CreateParty.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/DeleteParty.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/GetParty.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/JoinParty.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/LeaveParty.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/LinkDiscord.kt (2 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/Login.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/PartyUpdates.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Authentication.kt (2 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Party.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Player.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Settings.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/util/extension/Nbt.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/util/extension/Structures.kt (3 hunks)
  • common/src/main/kotlin/com/lambda/util/math/MathUtils.kt (1 hunks)
  • common/src/main/resources/lambda.accesswidener (1 hunks)
  • forge/build.gradle.kts (1 hunks)
  • gradle.properties (1 hunks)
💤 Files with no reviewable changes (3)
  • common/src/main/kotlin/com/lambda/command/commands/RpcCommand.kt
  • common/src/main/kotlin/com/lambda/http/api/rpc/v1/endpoints/UpdateParty.kt
  • common/src/main/kotlin/com/lambda/module/modules/client/DiscordRPC.kt
✅ Files skipped from review due to trivial changes (5)
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Settings.kt
  • gradle.properties
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Party.kt
  • common/src/main/java/com/lambda/mixin/world/ClientWorldMixin.java
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Player.kt
🧰 Additional context used
🪛 detekt (1.23.7)
common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt

[warning] 41-41: An empty default constructor can be removed.

(detekt.empty-blocks.EmptyDefaultConstructor)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build Lambda
🔇 Additional comments (24)
common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt (2)

133-160: LGTM! Documentation accurately reflects the simplified event handling.

The updated documentation clearly explains the predicate-based unsubscription mechanism and provides a helpful usage example.


161-165: LGTM! Simplified function signature improves type safety and usability.

The removal of the transformation logic and consistent use of type parameter T makes the code more focused and type-safe.

common/src/main/kotlin/com/lambda/network/api/v1/endpoints/LeaveParty.kt (2)

18-18: LGTM! Package restructuring improves code organization.

The package name change from http.api.rpc to network.api provides a cleaner and more focused organization of network-related code.


20-26: LGTM! Imports reflect improved modularity.

The imports demonstrate good practices:

  • Using Fuel's authentication extension for proper token handling
  • Centralizing network configuration through the Network module
  • Maintaining consistent package structure for models
common/src/main/kotlin/com/lambda/network/api/v1/endpoints/LinkDiscord.kt (1)

20-27: LGTM! Well-organized imports.

The imports are properly organized and include all necessary dependencies for HTTP requests, authentication, and network operations.

common/src/main/kotlin/com/lambda/network/api/v1/endpoints/CreateParty.kt (1)

18-26: LGTM! Well-organized imports and clear package structure.

The imports are specific and the package structure follows a good versioned API pattern.

common/src/main/kotlin/com/lambda/network/api/v1/endpoints/GetParty.kt (2)

18-18: No issues found on the package declaration.


21-26: Imports look consistent.
The added imports for Fuel authentication and references to the Network module align well with the new approach of retrieving the API URL, version, and access token from a central place.

common/src/main/kotlin/com/lambda/Lambda.kt (5)

20-23: No issues identified with these new imports.


34-34: No issues identified with the concurrent import.


46-49: No issues identified with the SSE-related imports.


51-51: No issues identified with the CountDownLatch import.


65-65: No issues identified with isDebug property.

common/src/main/kotlin/com/lambda/network/api/v1/endpoints/JoinParty.kt (1)

1-19: LGTM! Well-structured package with proper licensing.

The file follows best practices with a clear GPL v3 license header and proper package structure.

common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (2)

57-57: Warn about empty token fallback.
Returning an empty token string can unintentionally produce authorization calls without valid credentials. Ensure that the call sites handle such scenarios or fail fast to avoid silent authentication failures.


66-74: Ensure concurrency safety during encryption events.
serverId and hash are set in separate event listeners, and any race condition could lead to one being uninitialized by the time the other is used. Consider verifying that EncryptionResponse is guaranteed to fire after the EncryptionRequest, or introduce a synchronization mechanism if necessary.

common/src/main/kotlin/com/lambda/network/api/v1/endpoints/DeleteParty.kt (1)

29-33: Evaluate error handling to avoid silent failures.
The function returns a deserialized Party or an error under .third, but no further handling is performed. If the deletion fails, a caller might not realize it unless it explicitly checks the result. Consider wrapping the response in a more robust error-handling mechanism or returning a sealed type to enforce usage checks.

common/src/main/kotlin/com/lambda/util/math/MathUtils.kt (1)

41-41: LGTM! Clean and concise implementation.

The logCap function is well-placed in the MathUtils object and follows a functional style consistent with the rest of the file.

common/src/main/kotlin/com/lambda/command/commands/DiscordCommand.kt (1)

67-81: Consider consistent execution strategy.

The accept and refuse commands use runConcurrent while other commands use runSafe. Consider using a consistent execution strategy unless there's a specific reason for the difference.

Could you clarify why these commands require concurrent execution while others use safe execution?

common/src/main/resources/lambda.accesswidener (1)

71-73: LGTM! Well-structured additions.

The new Vec3i setter methods are properly categorized and follow the file's conventions.

common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt (1)

144-165: LGTM! Improved type safety and simplified implementation.

The changes improve the function by:

  • Making it more type-safe with a nullable return type.
  • Simplifying the implementation using Pointer.
forge/build.gradle.kts (1)

38-38: LGTM! Simplified property assignment syntax.

The change uses a more concise syntax for setting the accessWidenerPath property while maintaining the same functionality.

build.gradle.kts (2)

153-153: LGTM! Simplified compiler options syntax.

The change uses a more concise syntax for setting the jvmTarget property while maintaining the same functionality.


88-92:

Details

❓ Verification inconclusive

Verify the purpose of the development property.

The added property lambda.dev with a YouTube URL seems unusual. Please clarify its purpose and whether it's intended for development or debugging.


🌐 Web query:

What is the significance of the YouTube URL "youtu.be/RYnFIRc0k6E" in development configurations?

💡 Result:

The YouTube URL youtu.be/RYnFIRc0k6E represents a shortened link format used for sharing videos or configuring embedded players in development environments. Here’s its significance:

1. URL Shortening for Simplicity

  • The youtu.be domain acts as a built-in URL shortener for YouTube videos[6][9]. This makes links easier to share in contexts like social media or SMS[3].
  • Example: youtu.be/RYnFIRc0k6E redirects to the full video URL (e.g., youtube.com/watch?v=RYnFIRc0k6E).

2. Video ID Parameter

  • The alphanumeric string RYnFIRc0k6E is the unique video ID, critical for identifying content programmatically[5][6]. Developers use this ID to:
    • Embed videos via APIs[5].
    • Track analytics or integrate with third-party tools[5][7].

3. Dynamic Configuration via Parameters

  • Developers append query parameters to modify player behavior:
    • Example: youtu.be/RYnFIRc0k6E?autoplay=1&mute=1 starts playback automatically with muted audio[5].
    • Common parameters include:
      • t=25: Start video at 25 seconds[4][7].
      • rel=0: Disable related videos post-playback (deprecated in 2018)[5].
      • origin=https://example.com: Track embedding source for analytics[5].

4. Deprecated Features & Changes

  • Post-2018 updates deprecated parameters like showinfo, which previously hid video titles/uploader info[5].
  • The rel parameter now defaults to showing same-channel videos instead of disabling related content entirely[5].

Summary

The youtu.be URL simplifies sharing while enabling developers to customize video playback and tracking through query parameters. Its structure (video ID + modifiers) remains essential for integrations requiring precise control over embedded content[5][7].

Citations:


Clarify the lambda.dev Property Usage in Development Configurations

  • The configuration sets lambda.dev to a YouTube shortened URL (youtu.be/RYnFIRc0k6E), which is unconventional for development properties.
  • Please confirm whether this URL is intended for debugging, demonstration, or some specific runtime integration (e.g., embedding video support or a visual marker) in the development environment.
  • If it’s a temporary placeholder or part of experimental instrumentation, adding inline documentation or a comment explaining its purpose would be beneficial.

Comment on lines 34 to 38
Fuel.post("${apiUrl}/api/${apiVersion.value}/link/discord")
.jsonBody("""{ "token": "$discordToken" }""")
.authentication()
.bearer(Network.accessToken)
.responseObject<Authentication>().third
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve security and error handling.

The current implementation has several areas for improvement:

  1. Direct string interpolation in JSON body could be vulnerable to injection
  2. No error handling for failed requests
  3. URL construction could be more robust

Consider applying these improvements:

-	Fuel.post("${apiUrl}/api/${apiVersion.value}/link/discord")
-		.jsonBody("""{ "token": "$discordToken" }""")
-		.authentication()
-		.bearer(Network.accessToken)
-		.responseObject<Authentication>().third
+	try {
+		val endpoint = "$apiUrl/api/${apiVersion.value}/link/discord"
+		val jsonBody = mapOf("token" to discordToken)
+		
+		Fuel.post(endpoint)
+			.jsonBody(jsonBody)
+			.authentication()
+			.bearer(Network.accessToken)
+			.responseObject<Authentication>()
+			.third
+			.fold(
+				success = { it },
+				failure = { throw it }
+			)
+	} catch (e: Exception) {
+		throw IllegalStateException("Failed to link Discord account: ${e.message}", e)
+	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Fuel.post("${apiUrl}/api/${apiVersion.value}/link/discord")
.jsonBody("""{ "token": "$discordToken" }""")
.authentication()
.bearer(Network.accessToken)
.responseObject<Authentication>().third
try {
val endpoint = "$apiUrl/api/${apiVersion.value}/link/discord"
val jsonBody = mapOf("token" to discordToken)
Fuel.post(endpoint)
.jsonBody(jsonBody)
.authentication()
.bearer(Network.accessToken)
.responseObject<Authentication>()
.third
.fold(
success = { it },
failure = { throw it }
)
} catch (e: Exception) {
throw IllegalStateException("Failed to link Discord account: ${e.message}", e)
}

Comment on lines 28 to 32
fun createParty() =
Fuel.post("${apiUrl}/api/${apiVersion.value}/party/create")
.authentication()
.bearer(Network.accessToken)
.responseObject<Party>().third
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for network failures and token validation.

While the implementation is concise and follows good practices for authentication, consider adding:

  1. Validation of Network.accessToken before use
  2. Error handling for network failures
  3. Response status code validation

Here's a suggested implementation:

 fun createParty() =
+    if (Network.accessToken.isBlank()) {
+        Result.failure<Party>(IllegalStateException("Access token not available"))
+    } else try {
     Fuel.post("${apiUrl}/api/${apiVersion.value}/party/create")
         .authentication()
         .bearer(Network.accessToken)
-        .responseObject<Party>().third
+        .responseObject<Party>()
+        .third
+        .fold(
+            { Result.success(it) },
+            { Result.failure(it) }
+        )
+    } catch (e: Exception) {
+        Result.failure(e)
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fun createParty() =
Fuel.post("${apiUrl}/api/${apiVersion.value}/party/create")
.authentication()
.bearer(Network.accessToken)
.responseObject<Party>().third
fun createParty() =
if (Network.accessToken.isBlank()) {
Result.failure<Party>(IllegalStateException("Access token not available"))
} else try {
Fuel.post("${apiUrl}/api/${apiVersion.value}/party/create")
.authentication()
.bearer(Network.accessToken)
.responseObject<Party>()
.third
.fold(
{ Result.success(it) },
{ Result.failure(it) }
)
} catch (e: Exception) {
Result.failure(e)
}

Comment on lines 31 to 35
fun joinParty(
// The ID of the party.
// example: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
partyId: String,
) =
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation for partyId.

The function should validate that the partyId is not empty and matches the expected format before making the request.

 fun joinParty(
 	// The ID of the party.
 	// example: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
 	partyId: String,
-) =
+) {
+    require(partyId.isNotBlank()) { "Party ID cannot be empty" }
+    require(partyId.matches("[a-zA-Z0-9]+".toRegex())) { "Invalid party ID format" }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fun joinParty(
// The ID of the party.
// example: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
partyId: String,
) =
fun joinParty(
// The ID of the party.
// example: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
partyId: String,
) {
require(partyId.isNotBlank()) { "Party ID cannot be empty" }
require(partyId.matches("[a-zA-Z0-9]+".toRegex())) { "Invalid party ID format" }
// ... rest of the function implementation ...
}

Comment on lines 143 to 158
private suspend fun start() {
if (rpc.connected) return

runConcurrent { rpc.connect() } // TODO: Create a function that will wait until x seconds has passed or if the connection is successful
delay(1000)

val auth = rpc.applicationManager.authenticate()
val (authResp, error) = linkDiscord(discordToken = auth.accessToken)
if (error != null) {
warn(error.message.toString())
return toast("Failed to link the discord account to the minecraft auth")
}

updateToken(authResp)
discordAuth = auth
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle or timeout the Discord connection attempt.
rpc.connect() is invoked, but if Discord is not installed or the user is offline, the method may hang or fail silently. Incorporate a timeout or additional error handling to provide user feedback in case of a timeout or failure.

Comment on lines 36 to 38
Fuel.post("${apiUrl}/api/${apiVersion.value}/login")
.jsonBody("""{ "username": "$username", "hash": "$hash" }""")
.responseObject<Authentication>().third
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consider using a proper JSON serialization library.

Using string interpolation for JSON construction is prone to errors and security issues (e.g., if username contains quotes). Consider using Gson or Kotlinx.Serialization.

-		.jsonBody("""{ "username": "$username", "hash": "$hash" }""")
+		.jsonBody(gson.toJson(mapOf(
+			"username" to username,
+			"hash" to hash
+		)))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Fuel.post("${apiUrl}/api/${apiVersion.value}/login")
.jsonBody("""{ "username": "$username", "hash": "$hash" }""")
.responseObject<Authentication>().third
Fuel.post("${apiUrl}/api/${apiVersion.value}/login")
.jsonBody(gson.toJson(mapOf(
"username" to username,
"hash" to hash
)))
.responseObject<Authentication>().third

Comment on lines 35 to 43
fun NbtCompound.getVector(key: String): Vec3i {
// TODO: Handle other cases like array of values, capitalized keys, etc
val compound = getCompound(key)
val x = compound.getInt("x")
val y = compound.getInt("y")
val z = compound.getInt("z")

return Vec3i(x, y, z)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for missing or invalid NBT data.

The current implementation assumes the compound and its fields exist, which could lead to NullPointerException. Consider:

  1. Validating the compound exists
  2. Providing default values or handling missing coordinates
  3. Adding validation for coordinate values
 fun NbtCompound.getVector(key: String): Vec3i {
     // TODO: Handle other cases like array of values, capitalized keys, etc
-    val compound = getCompound(key)
-    val x = compound.getInt("x")
-    val y = compound.getInt("y")
-    val z = compound.getInt("z")
+    val compound = getCompound(key) ?: throw IllegalArgumentException("Vector compound not found for key: $key")
+    return Vec3i(
+        compound.getInt("x").takeIf { contains("x") } ?: 0,
+        compound.getInt("y").takeIf { contains("y") } ?: 0,
+        compound.getInt("z").takeIf { contains("z") } ?: 0
+    )
-    return Vec3i(x, y, z)
 }

Committable suggestion skipped: line range outside the PR's diff.

…d.kt

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1)

147-147: 🛠️ Refactor suggestion

Implement a timeout or error handling for rpc.connect().

A TODO is present to handle scenarios where Discord may not be installed or the user is offline. Without a timeout, the call might hang indefinitely.

Would you like me to provide an implementation that tracks elapsed time and cancels if rpc.connect() fails within a given limit?

🧹 Nitpick comments (2)
common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (2)

83-98: Possible concurrency risk with repeated coroutines.

Both listenConcurrently<WorldEvent.Join> (line 89) and onEnable { runConcurrent { … handleLoop() } } (line 96) can trigger handleLoop(). This may spawn multiple loops updating the same shared state (currentParty, rpc) simultaneously, risking data races or unexpected behavior.

Consider adding a guard to ensure that only one loop runs at a time or refactor the logic so that repeated calls won't conflict.


193-193: Revisit forced party exit on RPC disconnection.

Line 193 forces a party leave when rpc.connected becomes false. Users who briefly lose Discord connectivity might unintentionally lose their party.

Allow a grace period or reattempt connection before forcing a party exit.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cfa2e3f and f049fab.

📒 Files selected for processing (1)
  • common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build Lambda

Comment on lines 103 to 109
fun SafeContext.partyCreate() {
if (!isDiscordLinked) return warn("You did not link your discord account")
if (player.isInParty) {
if (player.isPartyOwner) deleteParty() else leaveParty()
return
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Extra curly brace causing a syntax error.

The extra brace on line 109 disrupts the block structure for partyCreate() and prevents successful compilation.

Apply this fix:

-    fun SafeContext.partyCreate() {
-        if (!isDiscordLinked) return warn("You did not link your discord account")
-        if (player.isInParty) {
-            if (player.isPartyOwner) deleteParty() else leaveParty()
-            return
-        }
-        }
+    fun SafeContext.partyCreate() {
+        if (!isDiscordLinked) return warn("You did not link your discord account")
+        if (player.isInParty) {
+            if (player.isPartyOwner) deleteParty() else leaveParty()
+            return
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fun SafeContext.partyCreate() {
if (!isDiscordLinked) return warn("You did not link your discord account")
if (player.isInParty) {
if (player.isPartyOwner) deleteParty() else leaveParty()
return
}
}
fun SafeContext.partyCreate() {
if (!isDiscordLinked) return warn("You did not link your discord account")
if (player.isInParty) {
if (player.isPartyOwner) deleteParty() else leaveParty()
return
}
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1)

70-70: Consider scoping the RPC client
The KDiscordIPC instance is defined at module level, yet its lifecycle depends on the module’s enable/disable state. In a multi-module system, consider scoping or re-initializing rpc more granularly to avoid potential leaks when toggling the module on/off.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f049fab and 7aae60e.

📒 Files selected for processing (2)
  • common/src/main/kotlin/com/lambda/command/commands/DiscordCommand.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • common/src/main/kotlin/com/lambda/command/commands/DiscordCommand.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build Lambda
🔇 Additional comments (3)
common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (3)

157-172: [Duplicate Comment] Handle or timeout the Discord connection attempt
A previous review mentioned adding a timeout or additional error handling if Discord is unavailable or not installed. Currently, rpc.connect() may hang. Implement a timeout to provide user feedback and prevent blocking the coroutine indefinitely.


195-207: Verify forced party leave upon Discord disconnection
When rpc.connected is false, the code calls leaveParty() if isDiscordLinked. This can abruptly remove a user from an active party if Discord times out or disconnects briefly. Verify that this is the intended behavior and not an unintended side effect.


89-94: Ensure concurrency safety in event listeners
Creating or joining a party from multiple listeners (e.g., on WorldEvent.Join, then in onEnable) might introduce race conditions or duplicate calls if the game condition triggers both. Verify that your concurrency model prevents simultaneous calls to partyCreate().

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (7)
common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (3)

59-59: Remove or rephrase unprofessional comment.

The comment “gson is too stupid” is unprofessional. Please update it to describe the technical limitation or reason more clearly.


80-88: Handle API authentication failures more robustly.

Currently, upon authentication failure, the code logs an error and returns false, but no fallback or retry is performed. Consider adding more robust error handling to inform users (e.g., in-game notification) or retry logic if necessary.


100-100: Use a more descriptive variable name.

The local variable addddd is unclear and could lead to confusion. Rename it to something more descriptive, like parsedServerAddress.

-            val addddd = ServerAddress.parse(authServer)
+            val parsedServerAddress = ServerAddress.parse(authServer)
common/src/main/kotlin/com/lambda/Lambda.kt (2)

61-61: Ensure debug flag usage is documented.

isDebug is inferred from system properties, which may lead to confusion for users or team members. Document this flag’s purpose or provide a clearer mechanism for toggling debug mode (e.g., environment variable or a config file).


92-110: Use consistent logging instead of println.

Currently, SSE events are printed via println. In production or debug builds, it’s often preferable to use a logger (Lambda.LOG or similar) so logs can be properly categorized and filtered.

common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (2)

195-207: Revisit forcing a party leave upon disconnection from Discord.
In handleLoop(), once rpc.connected becomes false, you call leaveParty() if isDiscordLinked. This might surprise users who want to remain in their party. Consider prompting or allowing them to stay in the party without active Discord Rich Presence.


209-228: Refactor the activity-building logic for maintainability.
The inline assembly of Discord activity details (lines 212-227) is functional, but centralizing repeated string concatenations and party logic into helper functions or a small builder class could boost clarity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7aae60e and e757afc.

📒 Files selected for processing (4)
  • common/src/main/kotlin/com/lambda/Lambda.kt (4 hunks)
  • common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Authentication.kt (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Authentication.kt
🔇 Additional comments (5)
common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (1)

90-92: Validate JWT decoding.

When decoding the base64-encoded token payload, an invalid or malformed JWT could cause runtime errors. Consider handling potential parsing exceptions and validating the token structure before deserializing.

common/src/main/kotlin/com/lambda/Lambda.kt (1)

79-85: Consider error handling for unavailable SSE endpoint.

If http://localhost:8080/api/v1/party/listen is unreachable, the current code flow might throw an exception in the future or hang. Consider implementing retry logic, fallback behavior, or user notification if the SSE endpoint is offline or returns an error.

common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (3)

51-66: Looks good!
The module initialization with default settings (e.g., Page, presence lines, etc.) appears consistent. The separation of "General" and "Party" settings is well-structured, and the default ranges for delay seem appropriate.


157-161: Consider adding a timeout or fallback for rpc.connect().
Because rpc.connect() is called without handling the possibility of Discord not being installed or user being offline, the method may hang/trap. This has been mentioned in a past review comment.

A potential improvement would be to wrap rpc.connect() in a function that times out or gracefully handles failure:

withTimeoutOrNull(5000) {
    rpc.connect()
} ?: warn("Discord connection timed out")

234-249: Guard against null or invalid context references in LineInfo.
Although unlikely in standard usage, calls such as mc.player?.health or mc.currentServerEntry could become null in uninitialized states or edge cases (e.g., reinitialization or dimension transitions). Ensure the code gracefully handles these corner cases.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (1)

74-80: ⚠️ Potential issue

Ensure thread-safe hash computation.

The hash computation lacks proper synchronization which could lead to race conditions.

 listenUnsafe<EncryptionResponse> { event ->
     if (event.secretKey.isDestroyed) return@listenUnsafe
-
-    hash = BigInteger(
-        NetworkEncryptionUtils.computeServerId(serverId, event.publicKey, event.secretKey)
-    ).toString(16)
+    synchronized(this) {
+        hash = BigInteger(
+            NetworkEncryptionUtils.computeServerId(serverId, event.publicKey, event.secretKey)
+        ).toString(16)
+    }
 }
🧹 Nitpick comments (7)
common/src/main/kotlin/com/lambda/network/api/v1/models/Party.kt (1)

26-26: Fix indentation: Replace tabs with spaces.

The @SerializedName annotations are using tabs for indentation while the rest of the file uses spaces. For consistency, replace tabs with spaces.

-	@SerializedName("id")
+    @SerializedName("id")
-	@SerializedName("join_secret")
+    @SerializedName("join_secret")
-	@SerializedName("leader")
+    @SerializedName("leader")
-	@SerializedName("creation")
+    @SerializedName("creation")
-	@SerializedName("players")
+    @SerializedName("players")

Also applies to: 31-31, 35-35, 40-40, 44-44

common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1)

106-117: Revisit forcing party deletion when already in a party.
Calling deleteParty or leaveParty unconditionally if the player is in a party might surprise users who want to remain in their existing party. Consider prompting the user or providing a separate command for forcibly recreating a party.

common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (5)

2-2: Update the copyright year.

The copyright year is set to 2025, which is in the future. Update it to the current year or the year when the code was written.

-* Copyright 2025 Lambda
+* Copyright 2024 Lambda

52-52: Add a meaningful module description.

The current description is a placeholder ("..."). Add a proper description that explains the module's purpose and functionality.

-    description = "...",
+    description = "Handles network authentication and API communication for Lambda client",

60-61: Improve state management and documentation.

Several issues to address:

  1. The TODO comment about caching should be implemented or tracked in an issue
  2. The comment about gson being "stupid" is unprofessional
  3. Consider adding thread safety annotations for mutable state variables
-    var apiAuth: Authentication? = null; private set // TODO: Cache
-    var deserialized: Data? = null; private set // gson is too stupid
+    @Volatile
+    var apiAuth: Authentication? = null; private set
+    @Volatile
+    var deserialized: Data? = null; private set // Deserialized JWT payload

Would you like me to create an issue to track the caching implementation?


129-129: Add documentation for token management.

The updateToken function lacks documentation explaining its purpose and usage.

+    /**
+     * Updates the authentication token for the API client.
+     * This is an internal function used during the authentication flow.
+     *
+     * @param auth The new authentication data, or null to clear the current authentication
+     */
     internal fun updateToken(auth: Authentication?) { apiAuth = auth }

131-134: Enhance API version management.

Consider adding version metadata to improve API version management.

-    enum class ApiVersion(val value: String) {
+    enum class ApiVersion(
+        val value: String,
+        val isDeprecated: Boolean = false,
+        val deprecatedSince: String? = null
+    ) {
         // We can use @Deprecated("Not supported") to remove old API versions in the future
-        V1("v1"),
+        V1("v1", isDeprecated = false),
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e757afc and a2f9a66.

📒 Files selected for processing (4)
  • common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/module/modules/client/Network.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/PartyUpdates.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/network/api/v1/models/Party.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • common/src/main/kotlin/com/lambda/network/api/v1/endpoints/PartyUpdates.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build Lambda
🔇 Additional comments (7)
common/src/main/kotlin/com/lambda/network/api/v1/models/Party.kt (3)

18-18: LGTM! Package name aligns with network module introduction.

The package name change from http.api to network.api better reflects the new network module architecture described in the PR objectives.


20-21: LGTM! Imports are clean and necessary.

The imports are minimal and appropriate for the class requirements.


23-46: LGTM! Well-structured data class with clear documentation.

The data class is well-documented with clear comments explaining each property's purpose. The removal of the settings property aligns with the model simplification mentioned in the summary.

common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (4)

83-101: Consider potential concurrency overlap in listener callbacks.
When both listenConcurrently<WorldEvent.Join> and the module's onEnable block call start() and handleLoop(), multiple coroutines might be launched if the module is toggled quickly. Although you guard re-initialization with if (rpc.connected) return in start(), confirm that no overlapping coroutines alter shared state unpredictably.


159-174: Handle or timeout the Discord connection attempt.
rpc.connect() might hang if Discord is not installed or offline. Add a timeout or improved error handling to give user feedback on failure.


197-209: Verify logic for forced party leave on RPC disconnection.
When the loop ends, the code calls leaveParty() if isDiscordLinked is still true. This may remove the user from a party even if they temporarily lost Discord connectivity. Confirm this aligns with user experience goals, or handle the party session more gracefully.


219-220: Check user identity exposure in smallImage URL.
The code references an external service (mc-heads.net) using the player's unique ID and username. This typically poses minimal risk, but verify that sharing these identifiers is acceptable from a privacy standpoint.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
common/src/main/kotlin/com/lambda/util/extension/World.kt (1)

30-30: Improve readability and add documentation.

While the logic is correct, the single-line implementation reduces readability. Consider expanding the when expression and adding documentation to explain the property's purpose, especially since it's used for network and Discord-related features.

Apply this diff to improve readability:

+/**
+ * Returns the current game context name.
+ * Used for network status and Discord Rich Presence.
+ */
-val SafeContext.worldName: String get() = when { mc.currentServerEntry != null -> "Multiplayer"; mc.isIntegratedServerRunning -> "Singleplayer"; else -> "Main Menu" }
+val SafeContext.worldName: String
+    get() = when {
+        mc.currentServerEntry != null -> "Multiplayer"
+        mc.isIntegratedServerRunning -> "Singleplayer"
+        else -> "Main Menu"
+    }
common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (2)

43-43: Consider making the module enabled by default or removing the commented-out code.
Currently, "enabledByDefault = true" is commented out. If you plan to ship the feature, consider enabling it or removing the comment to avoid confusion.


58-74: Unify initialization paths to avoid duplicating logic.
The code in listenOnce<WorldEvent.Join> and in the onEnable callback both initiate runConcurrent { start(); handleLoop() }. Consider consolidating them into a single entry point to reduce duplication and make the flow more predictable.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2f9a66 and db413fa.

📒 Files selected for processing (2)
  • common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (1 hunks)
  • common/src/main/kotlin/com/lambda/util/extension/World.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build Lambda
🔇 Additional comments (3)
common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt (3)

79-80: Apply a timeout or additional error handling when connecting to Discord.
rpc.connect() might hang or fail silently if Discord is unavailable. This repeats a previously noted concern about adding a timeout or error-handling callback to notify users.


95-99: Verify the logic to exit the update loop.
While this loop checks rpc.connected, ensure there's a straightforward exit path in scenarios where the socket never disconnects. Otherwise, you risk an indefinite loop that could hold resources.


107-107: Confirm that sharing player UUID with a third-party avatar service complies with privacy requirements.
Using the mc.gameProfile.id to fetch avatars from “mc-heads.net” may expose personally identifiable information. Confirm that this approach is acceptable.

@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 8, 2025
@lambda-client lambda-client deleted a comment from coderabbitai bot Mar 14, 2025
@emyfops emyfops merged commit 0837af3 into master Mar 14, 2025
3 checks passed
@emyfops emyfops deleted the feat/auth branch March 14, 2025 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage Requires labelling or review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants