Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3a3feba
aaaaaaa
emyfops Feb 5, 2025
b4950c8
Merge branch 'master' into feat/auth
emyfops Feb 14, 2025
1a57f45
Merge branch 'master' into feat/auth
emyfops Feb 14, 2025
d78be35
Merge branch 'master' into feat/auth
emyfops Feb 15, 2025
a863267
Discord and Network refactor
emyfops Feb 15, 2025
060a13b
Refactored the network, discord and http
emyfops Feb 17, 2025
9b8a9a9
Refactored the discord module
emyfops Feb 22, 2025
cfa2e3f
Fixed world join event
emyfops Feb 22, 2025
f049fab
Update common/src/main/kotlin/com/lambda/module/modules/client/Discor…
emyfops Feb 22, 2025
8608e25
Fixed discord delete logic
emyfops Feb 22, 2025
36f5737
Merge branch 'feat/auth' of https://github.com/Avanatiker/NeoLambda i…
emyfops Feb 22, 2025
7aae60e
Removed extra bracket
emyfops Feb 22, 2025
29b0709
Fixed code flow on failure
emyfops Feb 22, 2025
e757afc
Fixed stupid gson
emyfops Feb 22, 2025
a2f9a66
Updated logic and fixed bugs
emyfops Feb 23, 2025
db413fa
Parked the party feature locally
emyfops Feb 23, 2025
b925daa
Removed useless code
emyfops Feb 23, 2025
87a9700
Delete DiscordCommand.kt
emyfops Feb 23, 2025
dae5659
Added module description
emyfops Feb 23, 2025
106d137
Removed todo
emyfops Feb 23, 2025
9eb26ad
Push capes
emyfops Feb 28, 2025
68b483d
Merge branch 'master' into feat/auth
emyfops Feb 28, 2025
e070b3c
Update API to v1.1.0
emyfops Mar 7, 2025
ccb863f
Fold api responses
emyfops Mar 7, 2025
aa90562
Fix capes folder
emyfops Mar 7, 2025
2943614
Fixed texture downloading
emyfops Mar 7, 2025
13e692f
Cape feature
emyfops Mar 7, 2025
cf29f96
Fixed missing dependency
emyfops Mar 7, 2025
26d28a3
Update Discord.kt
emyfops Mar 14, 2025
21a89e0
Return if no values
emyfops Mar 14, 2025
3dd0fa2
Merge branch 'master' into feat/auth
emyfops Mar 14, 2025
acfd1aa
Merge conflict
emyfops Mar 14, 2025
f2fa357
Removed fix me
emyfops Mar 14, 2025
b5d1896
Fixed hash utils
emyfops Mar 14, 2025
d79aac4
Unused import
emyfops Mar 14, 2025
aa4206f
Log error instead of propagate
emyfops Mar 14, 2025
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
8 changes: 7 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ subprojects {

if (path == ":common") return@subprojects

loom.runs {
all {
property("lambda.dev", "youtu.be/RYnFIRc0k6E")
}
}

tasks {
register<Exec>("renderDoc") {
val javaHome = Jvm.current().javaHome
Expand Down Expand Up @@ -144,7 +150,7 @@ allprojects {
tasks {
compileKotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
jvmTarget = JvmTarget.JVM_17
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ val fabricLoaderVersion: String by project
val kotlinxCoroutinesVersion: String by project
val discordIPCVersion: String by project
val fuelVersion: String by project
val resultVersion: String by project

base.archivesName = "${base.archivesName.get()}-api"

Expand All @@ -46,9 +47,10 @@ dependencies {
implementation("com.github.Edouard127:KDiscordIPC:$discordIPCVersion")
implementation("com.pngencoder:pngencoder:0.15.0")

// Fuel HTTP library
// Fuel HTTP library and dependencies
implementation("com.github.kittinunf.fuel:fuel:$fuelVersion")
implementation("com.github.kittinunf.fuel:fuel-gson:$fuelVersion")
implementation("com.github.kittinunf.result:result-jvm:$resultVersion")

// Add Kotlin
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
import com.lambda.event.EventFlow;
import com.lambda.event.events.InventoryEvent;
import com.lambda.module.modules.render.NoRender;
import com.lambda.event.events.WorldEvent;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
import net.minecraft.network.packet.s2c.play.UpdateSelectedSlotS2CPacket;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -31,6 +35,24 @@

@Mixin(ClientPlayNetworkHandler.class)
public class ClientPlayNetworkHandlerMixin {
@Inject(method = "onGameJoin(Lnet/minecraft/network/packet/s2c/play/GameJoinS2CPacket;)V", at = @At("TAIL"))
void injectJoinPacket(GameJoinS2CPacket packet, CallbackInfo ci) {
EventFlow.post(new WorldEvent.Join());
}

@Inject(method = "handlePlayerListAction(Lnet/minecraft/network/packet/s2c/play/PlayerListS2CPacket$Action;Lnet/minecraft/network/packet/s2c/play/PlayerListS2CPacket$Entry;Lnet/minecraft/client/network/PlayerListEntry;)V", at = @At("TAIL"))
void injectPlayerList(PlayerListS2CPacket.Action action, PlayerListS2CPacket.Entry receivedEntry, PlayerListEntry currentEntry, CallbackInfo ci) {
if (action != PlayerListS2CPacket.Action.ADD_PLAYER) return;

var name = currentEntry.getProfile().getName();
var uuid = currentEntry.getProfile().getId();

if (receivedEntry.listed())
EventFlow.post(new WorldEvent.Player.Join(name, uuid, currentEntry));
else
EventFlow.post(new WorldEvent.Player.Leave(name, uuid, currentEntry));
}

@Inject(method = "onUpdateSelectedSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/util/thread/ThreadExecutor;)V", shift = At.Shift.AFTER), cancellable = true)
private void onUpdateSelectedSlot(UpdateSelectedSlotS2CPacket packet, CallbackInfo ci) {
if (EventFlow.post(new InventoryEvent.HotbarSlot.Sync(packet.getSlot())).isCanceled()) ci.cancel();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2025 Lambda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.lambda.mixin.render;

import com.lambda.module.modules.client.Capes;
import com.lambda.network.CapeManager;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.CapeFeatureRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

@Mixin(CapeFeatureRenderer.class)
public class CapeFeatureRendererMixin {
@ModifyExpressionValue(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/network/AbstractClientPlayerEntity;FFFFFF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/SkinTextures;capeTexture()Lnet/minecraft/util/Identifier;"))
Identifier renderCape(Identifier original, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, AbstractClientPlayerEntity player, float f, float g, float h, float j, float k, float l) {
if (!Capes.INSTANCE.isEnabled() || !CapeManager.INSTANCE.containsKey(player.getUuid())) return original;

return Identifier.of("lambda", CapeManager.INSTANCE.get(player.getUuid()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2025 Lambda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.lambda.mixin.render;

import com.lambda.module.modules.client.Capes;
import com.lambda.network.CapeManager;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.ElytraFeatureRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

@Mixin(ElytraFeatureRenderer.class)
public class ElytraFeatureRendererMixin<T extends LivingEntity> {
@ModifyExpressionValue(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/entity/LivingEntity;FFFFFF)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/SkinTextures;elytraTexture()Lnet/minecraft/util/Identifier;"))
Identifier renderElytra(Identifier original, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, T livingEntity, float f, float g, float h, float j, float k, float l) {
if (!Capes.INSTANCE.isEnabled() || !CapeManager.INSTANCE.containsKey(livingEntity.getUuid())) return original;

return Identifier.of("lambda", CapeManager.INSTANCE.get(livingEntity.getUuid()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@
import com.lambda.module.modules.render.WorldColors;
import com.lambda.util.math.ColorKt;
import net.minecraft.block.BlockState;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -33,6 +37,8 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.function.Supplier;

@Mixin(ClientWorld.class)
public class ClientWorldMixin {
@Inject(method = "addEntity", at = @At("HEAD"), cancellable = true)
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/kotlin/com/lambda/Lambda.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ object Lambda {
@JvmStatic
val mc: MinecraftClient by lazy { MinecraftClient.getInstance() }

val isDebug = System.getProperty("lambda.dev") != null

val gson: Gson = GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(KeyCode::class.java, KeyCodeSerializer)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 Lambda
* Copyright 2025 Lambda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -18,24 +18,36 @@
package com.lambda.command.commands

import com.lambda.brigadier.argument.literal
import com.lambda.brigadier.argument.string
import com.lambda.brigadier.argument.value
import com.lambda.brigadier.argument.word
import com.lambda.brigadier.execute
import com.lambda.brigadier.required
import com.lambda.command.LambdaCommand
import com.lambda.module.modules.client.DiscordRPC
import com.lambda.network.CapeManager.updateCape
import com.lambda.network.NetworkManager
import com.lambda.threading.runSafe
import com.lambda.util.extension.CommandBuilder

object RpcCommand : LambdaCommand(
name = "rpc",
description = "Discord Rich Presence commands.",
usage = "rpc <join [id] | accept>"
) {
object CapeCommand : LambdaCommand(
name = "cape",
usage = "set <id>",
description = "Sets your cape",
) {
override fun CommandBuilder.create() {
required(literal("join")) {
required(word("id")) { id ->
required(literal("set")) {
required(string("id")) { id ->
suggests { _, builder ->
NetworkManager.capes
.forEach { builder.suggest(it) }

builder.buildFuture()
}

execute {
DiscordRPC.join(id().value())
runSafe {
val cape = id().value()
updateCape(cape)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 Lambda
* Copyright 2025 Lambda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -15,15 +15,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.lambda.http.api.rpc.v1.endpoints
package com.lambda.config.configurations

import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.gson.responseObject
import com.lambda.http.api.rpc.v1.models.Party
import com.lambda.config.Configuration
import com.lambda.util.FolderRegister
import java.io.File

fun deleteParty(
endpoint: String,
version: String,
) =
Fuel.delete("$endpoint/api/$version/party/delete")
.responseObject<Party>().third
object UserConfig : Configuration() {
override val configName get() = "preferences"
override val primary: File = FolderRegister.config.resolve("$configName.json").toFile()
}
28 changes: 28 additions & 0 deletions common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ import com.lambda.threading.runSafe
import com.lambda.util.BlockUtils.blockState
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.client.network.PlayerListEntry
import net.minecraft.util.math.BlockPos
import net.minecraft.util.shape.VoxelShape
import net.minecraft.world.chunk.WorldChunk
import java.util.UUID
import kotlin.uuid.Uuid

/**
* Represents various events that can occur within the world.
Expand All @@ -36,6 +39,31 @@ import net.minecraft.world.chunk.WorldChunk
* occurrences in the game world.
*/
sealed class WorldEvent {
// ToDo: Add doc and determine if there's a better place for this event
// Represents the player joining the world
class Join() : Event

// ToDo: Maybe create a network event seal with some s2c events
sealed class Player {
/**
* Event triggered upon player joining
*/
data class Join(
val name: String,
val uuid: UUID,
val entry: PlayerListEntry,
) : Event

/**
* Event triggered upon player leaving
*/
data class Leave(
val name: String,
val uuid: UUID,
val entry: PlayerListEntry,
) : Event
}

/**
* Represents an event specific to chunk operations within the world.
*
Expand Down
20 changes: 8 additions & 12 deletions common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ class SafeListener<T : Event>(

/**
* This function registers a new [SafeListener] for a generic [Event] type [T].
* The [transform] is executed on the same thread where the [Event] was dispatched.
* The [transform] will only be executed when the context satisfies certain safety conditions.
* The [predicate] is executed on the same thread where the [Event] was dispatched.
* The [predicate] will only be executed when the context satisfies certain safety conditions.
* These conditions are met when none of the following [SafeContext] properties are null:
* - [SafeContext.world]
* - [SafeContext.player]
Expand All @@ -142,7 +142,7 @@ class SafeListener<T : Event>(
*
* This typically occurs when the user is in-game.
*
* After the [transform] is executed once, the [SafeListener] will be automatically unsubscribed.
* After the [predicate] is executed once, the [SafeListener] will be automatically unsubscribed.
*
* Usage:
* ```kotlin
Expand All @@ -156,24 +156,20 @@ class SafeListener<T : Event>(
* @param T The type of the event to listen for. This should be a subclass of Event.
* @param priority The priority of the listener. Listeners with higher priority will be executed first. The Default value is 0.
* @param alwaysListen If true, the listener will be executed even if it is muted. The Default value is false.
* @param transform The function used to transform the event into a value.
* @return The newly created and registered [SafeListener].
*/
inline fun <reified T : Event, reified E> Any.listenOnce(
inline fun <reified T : Event> Any.listenOnce(
priority: Int = 0,
alwaysListen: Boolean = false,
noinline predicate: SafeContext.(T) -> Boolean = { true },
noinline transform: SafeContext.(T) -> E? = { null },
): ReadWriteProperty<Any?, E?> {
val pointer = Pointer<E>()
): ReadWriteProperty<Any?, T?> {
val pointer = Pointer<T>()

val destroyable by selfReference<SafeListener<T>> {
SafeListener(priority, this@listenOnce, alwaysListen) { event ->
pointer.value = transform(event)
pointer.value = event

if (predicate(event) &&
pointer.value != null
) {
if (predicate(event)) {
val self by this@selfReference
EventFlow.syncListeners.unsubscribe(self)
}
Expand Down
Loading