Skip to content

Commit e070b3c

Browse files
committed
Update API to v1.1.0
1 parent 68b483d commit e070b3c

File tree

22 files changed

+516
-122
lines changed

22 files changed

+516
-122
lines changed

common/src/main/java/com/lambda/mixin/network/ClientPlayNetworkHandlerMixin.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import com.lambda.event.events.InventoryEvent;
2222
import com.lambda.event.events.WorldEvent;
2323
import net.minecraft.client.network.ClientPlayNetworkHandler;
24+
import net.minecraft.client.network.PlayerListEntry;
2425
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
26+
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
2527
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
2628
import net.minecraft.network.packet.s2c.play.UpdateSelectedSlotS2CPacket;
2729
import org.spongepowered.asm.mixin.Mixin;
@@ -36,6 +38,19 @@ void injectJoinPacket(GameJoinS2CPacket packet, CallbackInfo ci) {
3638
EventFlow.post(new WorldEvent.Join());
3739
}
3840

41+
@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"))
42+
void injectPlayerList(PlayerListS2CPacket.Action action, PlayerListS2CPacket.Entry receivedEntry, PlayerListEntry currentEntry, CallbackInfo ci) {
43+
if (action != PlayerListS2CPacket.Action.ADD_PLAYER) return;
44+
45+
var name = currentEntry.getProfile().getName();
46+
var uuid = currentEntry.getProfile().getId();
47+
48+
if (receivedEntry.listed())
49+
EventFlow.post(new WorldEvent.Player.Join(name, uuid, currentEntry));
50+
else
51+
EventFlow.post(new WorldEvent.Player.Leave(name, uuid, currentEntry));
52+
}
53+
3954
@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)
4055
private void onUpdateSelectedSlot(UpdateSelectedSlotS2CPacket packet, CallbackInfo ci) {
4156
if (EventFlow.post(new InventoryEvent.HotbarSlot.Sync(packet.getSlot())).isCanceled()) ci.cancel();

common/src/main/java/com/lambda/mixin/render/CapeFeatureRendererMixin.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,23 @@
1717

1818
package com.lambda.mixin.render;
1919

20+
import com.lambda.module.modules.client.Capes;
21+
import com.lambda.network.CapeManager;
2022
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
23+
import net.minecraft.client.network.AbstractClientPlayerEntity;
24+
import net.minecraft.client.render.VertexConsumerProvider;
2125
import net.minecraft.client.render.entity.feature.CapeFeatureRenderer;
26+
import net.minecraft.client.util.math.MatrixStack;
2227
import net.minecraft.util.Identifier;
2328
import org.spongepowered.asm.mixin.Mixin;
2429
import org.spongepowered.asm.mixin.injection.At;
2530

2631
@Mixin(CapeFeatureRenderer.class)
2732
public class CapeFeatureRendererMixin {
2833
@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;"))
29-
Identifier renderCape(Identifier original) {
30-
return new Identifier("lambda", "primary.png");
34+
Identifier renderCape(Identifier original, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, AbstractClientPlayerEntity player, float f, float g, float h, float j, float k, float l) {
35+
if (!Capes.INSTANCE.isEnabled() || !CapeManager.INSTANCE.containsKey(player.getUuid())) return original;
36+
37+
return Identifier.of("lambda", CapeManager.INSTANCE.get(player.getUuid()));
3138
}
3239
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.mixin.render;
19+
20+
import com.lambda.module.modules.client.Capes;
21+
import com.lambda.network.CapeManager;
22+
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
23+
import net.minecraft.client.render.VertexConsumerProvider;
24+
import net.minecraft.client.render.entity.feature.ElytraFeatureRenderer;
25+
import net.minecraft.client.util.math.MatrixStack;
26+
import net.minecraft.entity.LivingEntity;
27+
import net.minecraft.util.Identifier;
28+
import org.spongepowered.asm.mixin.Mixin;
29+
import org.spongepowered.asm.mixin.injection.At;
30+
31+
@Mixin(ElytraFeatureRenderer.class)
32+
public class ElytraFeatureRendererMixin<T extends LivingEntity> {
33+
@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;"))
34+
Identifier renderElytra(Identifier original, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, T livingEntity, float f, float g, float h, float j, float k, float l) {
35+
if (!Capes.INSTANCE.isEnabled() || !CapeManager.INSTANCE.containsKey(livingEntity.getUuid())) return original;
36+
37+
return Identifier.of("lambda", CapeManager.INSTANCE.get(livingEntity.getUuid()));
38+
}
39+
}

common/src/main/kotlin/com/lambda/Lambda.kt

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import com.lambda.core.Loader
2727
import com.lambda.gui.impl.clickgui.windows.tag.CustomModuleWindow
2828
import com.lambda.gui.impl.clickgui.windows.tag.TagWindow
2929
import com.lambda.module.tag.ModuleTag
30-
import com.lambda.threading.runConcurrent
3130
import com.lambda.util.KeyCode
3231
import com.mojang.authlib.GameProfile
3332
import com.mojang.blaze3d.systems.RenderSystem.recordRenderCall
@@ -39,12 +38,7 @@ import net.minecraft.util.math.BlockPos
3938
import org.apache.logging.log4j.LogManager
4039
import org.apache.logging.log4j.Logger
4140
import java.awt.Color
42-
import java.net.URI
43-
import java.net.http.HttpClient
44-
import java.net.http.HttpRequest
45-
import java.net.http.HttpResponse
4641
import java.util.*
47-
import java.util.concurrent.CountDownLatch
4842

4943

5044
object Lambda {
@@ -76,39 +70,6 @@ object Lambda {
7670
.create()
7771

7872
fun initialize(block: (Long) -> Unit) {
79-
runConcurrent {
80-
// Create an HttpClient
81-
val client = HttpClient.newHttpClient()
82-
83-
// Define the URI for the SSE stream
84-
val uri = URI.create("http://localhost:8080/api/v1/party/listen")
85-
86-
// Create an HttpRequest for the SSE stream
87-
val request = HttpRequest.newBuilder()
88-
.uri(uri)
89-
.header("Accept", "text/event-stream")
90-
.build()
91-
92-
// Create a CountDownLatch to wait for the events
93-
val latch = CountDownLatch(1)
94-
95-
// Send the request and handle the response asynchronously
96-
client.sendAsync(request, HttpResponse.BodyHandlers.ofLines())
97-
.thenAccept { response ->
98-
println("Connected to SSE stream")
99-
response.body().forEach { line ->
100-
if (line.startsWith("data:")) {
101-
val data = line.substring(5).trim()
102-
println("Received event data: $data")
103-
}
104-
}
105-
latch.countDown()
106-
}
107-
108-
// Wait until the response is received and handled
109-
latch.await()
110-
}
111-
11273
recordRenderCall {
11374
block(Loader.initialize())
11475
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.command.commands
19+
20+
import com.lambda.brigadier.CommandResult.Companion.failure
21+
import com.lambda.brigadier.CommandResult.Companion.success
22+
import com.lambda.brigadier.argument.string
23+
import com.lambda.brigadier.argument.value
24+
import com.lambda.brigadier.executeWithResult
25+
import com.lambda.brigadier.required
26+
import com.lambda.command.LambdaCommand
27+
import com.lambda.network.NetworkManager
28+
import com.lambda.network.api.v1.endpoints.setCape
29+
import com.lambda.util.extension.CommandBuilder
30+
31+
object CapeCommand : LambdaCommand(
32+
name = "cape",
33+
usage = "set <id>",
34+
description = "Sets your cape",
35+
) {
36+
override fun CommandBuilder.create() {
37+
required(string("id")) { id ->
38+
suggests { _, builder ->
39+
NetworkManager.capes
40+
.forEach { builder.suggest(it) }
41+
42+
builder.buildFuture()
43+
}
44+
45+
executeWithResult {
46+
val cape = id().value()
47+
setCape(cape)
48+
.fold(
49+
success = { NetworkManager.cape = cape; success() },
50+
failure = { failure(it) },
51+
)
52+
}
53+
}
54+
}
55+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.config.configurations
19+
20+
import com.lambda.config.Configuration
21+
import com.lambda.util.FolderRegister
22+
import java.io.File
23+
24+
object UserConfig : Configuration() {
25+
override val configName get() = "preferences"
26+
override val primary: File = FolderRegister.config.resolve("$configName.json").toFile()
27+
}

common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@ import com.lambda.threading.runSafe
2424
import com.lambda.util.BlockUtils.blockState
2525
import net.minecraft.block.BlockState
2626
import net.minecraft.block.Blocks
27+
import net.minecraft.client.network.PlayerListEntry
2728
import net.minecraft.util.math.BlockPos
2829
import net.minecraft.util.shape.VoxelShape
2930
import net.minecraft.world.chunk.WorldChunk
31+
import java.util.UUID
32+
import kotlin.uuid.Uuid
3033

3134
/**
3235
* Represents various events that can occur within the world.
@@ -40,6 +43,27 @@ sealed class WorldEvent {
4043
// Represents the player joining the world
4144
class Join() : Event
4245

46+
// ToDo: Maybe create a network event seal with some s2c events
47+
sealed class Player {
48+
/**
49+
* Event triggered upon player joining
50+
*/
51+
data class Join(
52+
val name: String,
53+
val uuid: UUID,
54+
val entry: PlayerListEntry,
55+
) : Event
56+
57+
/**
58+
* Event triggered upon player leaving
59+
*/
60+
data class Leave(
61+
val name: String,
62+
val uuid: UUID,
63+
val entry: PlayerListEntry,
64+
) : Event
65+
}
66+
4367
/**
4468
* Represents an event specific to chunk operations within the world.
4569
*
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.module.modules.client
19+
20+
import com.lambda.module.Module
21+
import com.lambda.module.tag.ModuleTag
22+
23+
object Capes : Module(
24+
name = "Capes",
25+
description = "Display custom capes",
26+
defaultTags = setOf(ModuleTag.CLIENT),
27+
)

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import com.lambda.event.EventFlow
2323
import com.lambda.event.events.WorldEvent
2424
import com.lambda.event.listener.SafeListener.Companion.listenOnce
2525
import com.lambda.module.Module
26-
import com.lambda.module.modules.client.Network.updateToken
2726
import com.lambda.module.tag.ModuleTag
27+
import com.lambda.network.NetworkManager.updateToken
2828
import com.lambda.network.api.v1.endpoints.linkDiscord
2929
import com.lambda.threading.runConcurrent
3030
import com.lambda.util.Communication.warn
@@ -83,7 +83,7 @@ object Discord : Module(
8383
val (authResp, error) = linkDiscord(discordToken = auth.accessToken)
8484
if (error != null) return warn("Failed to link the discord account to the minecraft auth")
8585

86-
updateToken(authResp)
86+
updateToken(authResp!!)
8787
discordAuth = auth
8888
}
8989

@@ -115,8 +115,8 @@ object Discord : Module(
115115
VERSION({ Lambda.VERSION }),
116116
WORLD({ worldName }),
117117
USERNAME({ mc.session.username }),
118-
HEALTH({ "${mc.player?.health ?: 0} HP" }),
119-
HUNGER({ "${mc.player?.hungerManager?.foodLevel ?: 0} Hunger" }),
118+
HEALTH({ "${player.health} HP" }),
119+
HUNGER({ "${player.hungerManager.foodLevel} Hunger" }),
120120
DIMENSION({ dimensionName }),
121121
FPS({ "${mc.currentFps} FPS" });
122122
}

0 commit comments

Comments
 (0)