Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
34e800e
Fix: Lambda main
emyfops Mar 24, 2024
8845e69
Update .gitignore
emyfops Mar 24, 2024
92e3456
Test: Discord rpc
emyfops Mar 24, 2024
f3e0015
Added rpc coroutine scope
emyfops Mar 24, 2024
71f001c
Fix: Crash on disconnect
emyfops Mar 24, 2024
05146f4
Added shutdown hook
emyfops Mar 24, 2024
ef73ea7
Fix: Enum crash
emyfops Mar 24, 2024
39368e9
Merge branch 'master' into feature/discordrpc
emyfops Mar 24, 2024
5dbd361
Fix: Rpc not showing on profile
emyfops Mar 24, 2024
e75f8aa
Refactor: Use same thread for setup and connect
emyfops Mar 24, 2024
650575b
Added error event
emyfops Mar 24, 2024
1452852
Removed useless events
emyfops Mar 24, 2024
32b5dc7
Merge branch 'master' into feature/discordrpc
Avanatiker Mar 25, 2024
b5c844f
Added small image player
emyfops Mar 25, 2024
4464cf1
Fix DiscordRPC
Avanatiker Mar 26, 2024
0f11063
Feature: Discord RPC
emyfops Mar 27, 2024
89cae7e
Added extremely detailled kdoc for shutdown hook
emyfops Mar 30, 2024
d89bf47
Feature: Connection state events
emyfops Mar 30, 2024
b075f0c
Added kdoc
emyfops Mar 30, 2024
57d3080
Feature: Minimal http wrapper
emyfops Mar 30, 2024
ee60145
Fixed comment
emyfops Mar 30, 2024
535b891
Feature: RPC http request
emyfops Mar 30, 2024
3e7a1a6
Merge branch 'master' into feature/discordrpc
Avanatiker Apr 11, 2024
af2c2c1
Fix: Forge doesn't support ModifyArgs
emyfops Apr 13, 2024
dd52500
Fix: Missing import
emyfops Apr 13, 2024
eab5b12
Disable transitive include
emyfops Apr 13, 2024
dfc909d
Merge conflicts
emyfops Apr 15, 2024
8cdb410
Fix: Quilt
emyfops Apr 15, 2024
055ef2d
Merge branch 'master' into feature/discordrpc
emyfops Apr 22, 2024
63b7327
Merge branch 'master' into feature/discordrpc
emyfops Apr 27, 2024
ffcf4f6
Fix: thedarkcolour/KotlinForForge/94
emyfops Apr 27, 2024
3d6c729
Merge branch 'master' into feature/discordrpc
emyfops Apr 27, 2024
0e4a159
Added all current methods
emyfops Apr 28, 2024
0346552
Refactor!: Up to date with server
emyfops Apr 28, 2024
a9f875e
Working RPC system
emyfops Apr 28, 2024
087b0c3
Refactor: Pseudo setting consumer
emyfops Apr 28, 2024
56de50c
Feature: Join a party later with commands
emyfops Apr 29, 2024
9a89c7e
funny comment
emyfops Apr 29, 2024
32a242b
Fix: Token is not authorization
emyfops Apr 29, 2024
2922ac5
Create MiscArguments.kt
emyfops Apr 29, 2024
776f3c6
Fixed rpc command builder
emyfops Apr 29, 2024
8db6369
Merge branch 'master' into feature/discordrpc
emyfops May 19, 2024
816190e
Merge conflicts
emyfops May 19, 2024
b724798
Merge branch 'master' into feature/discordrpc
emyfops May 19, 2024
1d048d4
Update gradle.properties
emyfops May 19, 2024
6e659a9
Fix: RPC Connection
emyfops May 19, 2024
5a68b2e
Fix: IPC not found
emyfops May 19, 2024
f0a01e7
Add exception info on error
emyfops May 19, 2024
dfc8f97
Better error format
emyfops May 19, 2024
00b17af
Temp fix xray
emyfops May 20, 2024
80b7fa7
Better errors
emyfops May 26, 2024
51eeaab
Merge branch 'master' into feature/discordrpc
emyfops May 26, 2024
8fbe152
Update DiscordRPC.kt
emyfops May 26, 2024
ba3073d
Refactor: API update
emyfops Jun 28, 2024
4480696
Merge branch 'master' into feature/discordrpc
Avanatiker Jun 28, 2024
744a80a
Merge branch 'master' into feature/discordrpc
emyfops Jul 5, 2024
90b600e
Refactor: Use our fork
emyfops Jul 5, 2024
d5a11cb
Added test logging
emyfops Jul 5, 2024
4962c3f
Update lambda.mixins.common.json
emyfops Jul 5, 2024
f8adab2
Temp force variable
emyfops Jul 5, 2024
6975fa9
Temp: Local party
emyfops Jul 5, 2024
074304c
Update lambda.mixins.common.json
emyfops Jul 5, 2024
c0a2b8e
Fixed the update delay
emyfops Jul 5, 2024
c33b9f9
Merge branch 'master' into feature/discordrpc
emyfops Jul 8, 2024
e0e17a7
Merge branch 'master' into feature/discordrpc
emyfops Aug 19, 2024
b10d7f6
Update Player.kt
emyfops Aug 19, 2024
fda87bb
feat: cached downloads & request builder
emyfops Aug 19, 2024
7e7182e
added request builder to endpoints
emyfops Aug 19, 2024
4943a72
several fixes
emyfops Aug 19, 2024
ba1b21b
Update ConnectionEvent.kt
emyfops Aug 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ logs/

### Architectury ###
.architectury-transformer/

### Kotlin ###
*.kotlin_module
.kotlin/
8 changes: 4 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ allprojects {
base.archivesName = modId

repositories {
maven("https://api.modrinth.com/maven")
maven("https://jitpack.io")
maven("https://maven.shedaniel.me/") { name = "Architectury" }
maven("https://maven.shedaniel.me/") // Architectury
maven("https://maven.terraformersmc.com/releases/")
maven("https://babbaj.github.io/maven/")
maven("https://babbaj.github.io/maven/") // Baritone
maven("https://jitpack.io") // KDiscordIPC
mavenCentral()

// Allow the use of local libraries
flatDir {
Expand Down
2 changes: 2 additions & 0 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ val modId: String by project
val fabricLoaderVersion: String by project
val kotlinVersion: String by project
val kotlinxCoroutinesVersion: String by project
val discordIPCVersion: String by project

architectury { common("fabric", "forge", "neoforge") }

Expand All @@ -21,6 +22,7 @@ dependencies {

// Add dependencies on the required Kotlin modules.
implementation("org.reflections:reflections:0.10.2")
implementation("com.github.Edouard127:KDiscordIPC:$discordIPCVersion")

// Add Kotlin
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.lambda.mixin;
package com.lambda.mixin.network;

import com.lambda.event.EventFlow;
import com.lambda.event.events.ConnectionEvent;
Expand Down Expand Up @@ -73,7 +73,7 @@ private void onConnect(
ConnectionIntent intent,
CallbackInfo ci
) {
EventFlow.post(new ConnectionEvent.Connect(address, port, listener, intent));
EventFlow.post(new ConnectionEvent.Connect.Pre(address, port, listener, intent));
}

@Inject(method = "disconnect(Lnet/minecraft/text/Text;)V", at = @At("HEAD"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.lambda.mixin.network;

import com.lambda.event.EventFlow;
import com.lambda.event.events.ConnectionEvent;
import com.lambda.module.modules.client.DiscordRPC;
import net.minecraft.client.network.ClientLoginNetworkHandler;
import net.minecraft.network.packet.s2c.login.LoginSuccessS2CPacket;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(ClientLoginNetworkHandler.class)
public class ClientLoginNetworkMixin {

@Inject(method = "onSuccess(Lnet/minecraft/network/packet/s2c/login/LoginSuccessS2CPacket;)V", at = @At("HEAD"))
private void onSuccess(LoginSuccessS2CPacket packet, CallbackInfo ci) {
EventFlow.post(new ConnectionEvent.Connect.Post(packet.getProfile()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.lambda.mixin.network;

import com.lambda.event.EventFlow;
import com.lambda.event.events.ConnectionEvent;
import net.minecraft.network.packet.c2s.handshake.ConnectionIntent;
import net.minecraft.network.packet.c2s.handshake.HandshakeC2SPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(HandshakeC2SPacket.class)
public class HandshakeC2SPacketMixin {
@Inject(method = "<init>(ILjava/lang/String;ILnet/minecraft/network/packet/c2s/handshake/ConnectionIntent;)V", at = @At("TAIL"))
private void onHandshakeC2SPacket(int i, String string, int j, ConnectionIntent connectionIntent, CallbackInfo ci) {
EventFlow.post(new ConnectionEvent.Connect.Handshake(i, string, j, connectionIntent));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.lambda.mixin.network;

import com.lambda.event.EventFlow;
import com.lambda.event.events.ConnectionEvent;
import net.minecraft.network.packet.c2s.login.LoginHelloC2SPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.UUID;

@Mixin(LoginHelloC2SPacket.class)
public class LoginHelloC2SPacketMixin {
@Inject(method = "<init>(Ljava/lang/String;Ljava/util/UUID;)V", at = @At("TAIL"))
private void onLoginHelloC2SPacket(String string, UUID uUID, CallbackInfo ci) {
EventFlow.post(new ConnectionEvent.Connect.Login.Hello(string, uUID));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.lambda.mixin.network;

import com.lambda.event.EventFlow;
import com.lambda.event.events.ConnectionEvent;
import net.minecraft.network.packet.c2s.login.LoginKeyC2SPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import javax.crypto.SecretKey;
import java.security.PublicKey;

@Mixin(LoginKeyC2SPacket.class)
public class LoginKeyC2SPacketMixin {
@Inject(method = "<init>(Ljavax/crypto/SecretKey;Ljava/security/PublicKey;[B)V", at = @At("TAIL"))
private void onLoginKeyC2SPacket(SecretKey secretKey, PublicKey publicKey, byte[] nonce, CallbackInfo ci) {
// Please note this won't work if the server is offline mode because the player doesn't
// fetch the server's public key.
EventFlow.post(new ConnectionEvent.Connect.Login.Key(secretKey, publicKey, nonce));
}
}
1 change: 1 addition & 0 deletions common/src/main/kotlin/com/lambda/Lambda.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ object Lambda {
const val MOD_NAME = "Lambda"
const val MOD_ID = "lambda"
const val SYMBOL = "λ"
const val APP_ID = "1221289599427416127"
val VERSION: String = LoaderInfo.getVersion()
val LOG: Logger = LogManager.getLogger(SYMBOL)

Expand Down
31 changes: 31 additions & 0 deletions common/src/main/kotlin/com/lambda/command/commands/RpcCommand.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.lambda.command.commands

import com.lambda.brigadier.*
import com.lambda.brigadier.argument.literal
import com.lambda.brigadier.argument.value
import com.lambda.brigadier.argument.word
import com.lambda.command.LambdaCommand
import com.lambda.module.modules.client.DiscordRPC
import com.lambda.util.extension.CommandBuilder

object RpcCommand : LambdaCommand(
name = "rpc",
description = "Discord Rich Presence commands.",
usage = "rpc <join [id] | accept>"
) {
override fun CommandBuilder.create() {
required(literal("join")) {
required(word("id")) { id ->
execute {
DiscordRPC.join(id().value())
}
}
}

required(literal("accept")) {
execute {
DiscordRPC.join()
}
}
}
}
90 changes: 83 additions & 7 deletions common/src/main/kotlin/com/lambda/event/events/ConnectionEvent.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,93 @@
package com.lambda.event.events

import com.lambda.event.Event
import com.mojang.authlib.GameProfile
import net.minecraft.network.listener.PacketListener
import net.minecraft.network.packet.c2s.handshake.ConnectionIntent
import net.minecraft.text.Text
import java.security.PublicKey
import java.util.UUID
import javax.crypto.SecretKey

abstract class ConnectionEvent : Event {
class Connect(
val host: String,
val port: Int,
val listener: PacketListener,
val intent: ConnectionIntent,
) : ConnectionEvent()
/**
* Sealed class representing connection events.
*/
sealed class ConnectionEvent : Event {
/**
* Sealed class representing various stages of connection establishment.
*/
sealed class Connect {
/**
* Event representing a pre-connection attempt.
* @property address The address of the connection attempt.
* @property port The port of the connection attempt.
* @property listener The packet listener associated with the connection.
* @property intent The connection intent.
*/
class Pre(
val address: String,
val port: Int,
val listener: PacketListener,
val intent: ConnectionIntent,
) : ConnectionEvent()

/**
* Event representing a handshake during connection.
* @property protocolVersion The protocol version of the connection.
* @property address The address of the connection attempt.
* @property port The port of the connection attempt.
* @property intent The connection intent.
*/
class Handshake(
val protocolVersion: Int,
val address: String,
val port: Int,
val intent: ConnectionIntent,
) : ConnectionEvent()

/**
* Sealed class representing login-related connection events.
*/
sealed class Login : ConnectionEvent() {
/**
* Event representing a hello message during login.
* @property name The name associated with the login.
* @property uuid The UUID associated with the login.
*/
class Hello(
val name: String,
val uuid: UUID,
) : ConnectionEvent()

/**
* Event representing the exchange of cryptographic keys during login.
* @property secretKey The secret key exchanged during login.
* @property publicKey The public key exchanged during login.
* @property nonce The nonce associated with the login.
*
* The secret key MUST ABSOLUTELY be, if stored, destroyed after use to avoid security vulnerabilities.
* This can be done by calling the `destroy()` method on the secret key object.
* We are NOT responsible for any incidents that may occur due to improper handling of cryptographic keys.
*/
class Key(
val secretKey: SecretKey,
val publicKey: PublicKey,
val nonce: ByteArray,
) : ConnectionEvent()
}

/**
* Event representing post-connection actions.
* @property profile The game profile associated with the connection.
*/
class Post(
val profile: GameProfile,
) : ConnectionEvent()
}

/**
* Event representing a disconnection.
* @property reason The reason for disconnection.
*/
class Disconnect(val reason: Text) : ConnectionEvent()
}
34 changes: 34 additions & 0 deletions common/src/main/kotlin/com/lambda/http/Extensions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.lambda.http

import com.lambda.Lambda
import java.net.URLEncoder

/**
* Extension property to convert a map to a URL query string.
*/
val Map<String, Any>.query: String
get() = map { (key, value) -> "$key=${value.urlEncoded}" }.joinToString("&")

/**
* Extension property to URL encode a string.
*/
val Any.urlEncoded: String get() = URLEncoder.encode(toString(), "UTF-8")

/**
* Extension function to convert a map to a JSON string.
*/
fun Map<String, Any>.toJson(): String = Lambda.gson.toJson(this)

/**
* Try-catch block wrapped with a default value.
*/
fun <T> tryOrDefault(default: T, block: () -> T): T = try {
block()
} catch (e: Exception) {
default
}

/**
* Try-catch block wrapped with null
*/
fun <T> tryOrNull(block: () -> T): T? = tryOrDefault(null, block)
15 changes: 15 additions & 0 deletions common/src/main/kotlin/com/lambda/http/Method.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.lambda.http

/**
* Enum representing HTTP methods.
*/
enum class Method {
GET,
HEAD,
POST,
PUT,
DELETE,
OPTIONS,
TRACE,
PATCH;
}
Loading