Skip to content

Commit b4252d0

Browse files
committed
Merge branch 'master' into refactor/ui
2 parents 687dec0 + 5ec18b6 commit b4252d0

File tree

101 files changed

+3122
-2152
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+3122
-2152
lines changed

.github/ISSUE_TEMPLATE/BUG_REPORT.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Bug Report
22
description: File a bug report.
3-
title: "[Version] [Mod loader] Bug: "
3+
title: "[Version] Bug: "
44
assignees:
55
- Edouard127
66
body:

.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Feature
22
description: Request or implement a feature.
3-
title: "[Version] [Mod loader] Feat: "
3+
title: "[Version] Feat: "
44
assignees:
55
- Edouard127
66
body:

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
blank_issues_enabled: false
1+
blank_issues_enabled: true
22
contact_links:
33
- name: Lambda Discord Server
44
url: https://discord.gg/QjfBxJzE5x

.github/workflows/build.yml

Lines changed: 9 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,26 @@ name: Build Lambda
33
on:
44
push:
55
branches:
6-
- '**'
6+
- 'master'
7+
pull_request:
78

89
jobs:
9-
check-runner:
10-
name: Check Runner Availability
11-
runs-on: ubuntu-latest
12-
13-
outputs:
14-
runner-label: ${{ steps.set-runner.outputs.runner-label }}
15-
16-
steps:
17-
- name: Set runner
18-
id: set-runner
19-
run: |
20-
runners=$(curl -v -s -H "Accept: application/vnd.github+json" -H "Authorization: token ${{ secrets.REPO_ACCESS_TOKEN }}" "https://api.github.com/repos/${{ github.repository }}/actions/runners" --http1.1)
21-
if [ $? -ne 0 ]; then
22-
echo "Error: Failed to fetch runners from GitHub API" >&2
23-
exit 1
24-
fi
25-
26-
runners_count=$(echo "$runners" | jq '.runners | length')
27-
if [ "$runners_count" -eq 0 ]; then
28-
echo "No runners available or failed to retrieve runners." >&2
29-
echo "runner-label=ubuntu-latest" >> $GITHUB_OUTPUT
30-
exit 0
31-
fi
32-
33-
available=$(echo "$runners" | jq '.runners[] | select(.status == "online" and .busy == false and .labels[] .name == "self-hosted")')
34-
if [ $? -ne 0 ]; then
35-
echo "Error: Failed to parse JSON response" >&2
36-
exit 1
37-
fi
38-
39-
if [ -n "$available" ]; then
40-
echo "runner-label=lambda-linux-runner" >> $GITHUB_OUTPUT
41-
else
42-
echo "runner-label=ubuntu-latest" >> $GITHUB_OUTPUT
43-
fi
4410
build:
4511
concurrency:
4612
group: ${{ github.workflow }}-${{ github.ref }}
4713
cancel-in-progress: true
48-
49-
needs: check-runner
50-
runs-on: ${{ needs.check-runner.outputs.runner-label }}
5114

5215
name: Build Lambda
16+
runs-on: ubuntu-latest
17+
5318
permissions:
5419
contents: write
20+
5521
env:
5622
SEGMENT_DOWNLOAD_TIMEOUT_MINS: '5'
5723
steps:
5824
- name: Checkout Repository
59-
uses: actions/checkout@v4.1.1
25+
uses: actions/checkout@v4
6026

6127
- name: Set current date as env variable
6228
run: echo "DATE=$(date +'%Y-%m-%dT%H:%M:%S')" >> $GITHUB_ENV
@@ -65,11 +31,11 @@ jobs:
6531
id: vars
6632
run: echo "COMMIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
6733

68-
- name: Set-Up JDK 17
34+
- name: Set-Up JDK
6935
uses: actions/setup-java@v4
7036
with:
7137
distribution: 'temurin'
72-
java-version: '17'
38+
java-version: '21'
7339
architecture: x64
7440
cache: 'gradle'
7541

@@ -81,7 +47,7 @@ jobs:
8147
all: true
8248

8349
- name: Build Lambda
84-
run: ./gradlew build
50+
run: ./gradlew build --no-daemon
8551

8652
- name: Rename Files with Commit Hash
8753
run: |
@@ -111,8 +77,6 @@ jobs:
11177
### [Lambda Forge ${{ steps.all.outputs.modVersion }} ${{ steps.all.outputs.minecraftVersion }} (${{ env.COMMIT_HASH }})](https://r2-bucket.edouard127.christmas/${{ env.DATE }}-${{ env.COMMIT_HASH }}/lambda-forge-${{ steps.all.outputs.modVersion }}+${{ steps.all.outputs.minecraftVersion }}-${{ env.COMMIT_HASH }}.jar)
11278
11379
#### [API (Developer Dependency)](https://r2-bucket.edouard127.christmas/${{ env.DATE }}-${{ env.COMMIT_HASH }}/lambda-api-${{ steps.all.outputs.modVersion }}+${{ steps.all.outputs.minecraftVersion }}-${{ env.COMMIT_HASH }}.jar)
114-
115-
**Runner:** \`${{ needs.check-runner.outputs.runner-label }}\`
11680
EOF
11781
11882
- name: Failover Upload

.github/workflows/publish-docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ name: Publish Dokka Documentation
22

33
on:
44
push:
5-
branches:
6-
- 'master'
5+
tags:
6+
- '*'
77

88
jobs:
99
build:

build.gradle.kts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ val Project.loom: LoomGradleExtensionAPI
3838
get() = (this as ExtensionAware).extensions.getByName("loom") as LoomGradleExtensionAPI
3939

4040
plugins {
41-
kotlin("jvm") version "2.0.20"
42-
id("org.jetbrains.dokka") version "1.9.20"
41+
kotlin("jvm") version "2.1.20"
42+
id("org.jetbrains.dokka") version "2.0.0"
4343
id("architectury-plugin") version "3.4-SNAPSHOT"
44-
id("dev.architectury.loom") version "1.7-SNAPSHOT" apply false
44+
id("dev.architectury.loom") version "1.9-SNAPSHOT" apply false
4545
id("com.github.johnrengelman.shadow") version "8.1.1" apply false
4646
id("maven-publish")
4747
}

common/build.gradle.kts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ val modId: String by project
2121
val fabricLoaderVersion: String by project
2222
val kotlinxCoroutinesVersion: String by project
2323
val discordIPCVersion: String by project
24-
val fuelVersion: String by project
25-
val resultVersion: String by project
24+
val ktorVersion: String by project
25+
val mockitoKotlin: String by project
26+
val mockitoInline: String by project
27+
val mockkVersion: String by project
2628

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

@@ -47,16 +49,23 @@ dependencies {
4749
implementation("com.github.Edouard127:KDiscordIPC:$discordIPCVersion")
4850
implementation("com.pngencoder:pngencoder:0.15.0")
4951

50-
// Fuel HTTP library and dependencies
51-
implementation("com.github.kittinunf.fuel:fuel:$fuelVersion")
52-
implementation("com.github.kittinunf.fuel:fuel-gson:$fuelVersion")
53-
implementation("com.github.kittinunf.result:result-jvm:$resultVersion")
52+
// Ktor
53+
implementation("io.ktor:ktor-client-core:$ktorVersion")
54+
implementation("io.ktor:ktor-client-cio:$ktorVersion")
55+
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
56+
implementation("io.ktor:ktor-serialization-gson:$ktorVersion")
5457

5558
// Add Kotlin
5659
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
5760

5861
// Baritone
5962
modImplementation("baritone-api:baritone-unoptimized-fabric:1.10.2") { isTransitive = false }
63+
64+
// Test implementations
65+
testImplementation(kotlin("test"))
66+
testImplementation("org.mockito.kotlin:mockito-kotlin:$mockitoKotlin")
67+
testImplementation("org.mockito:mockito-inline:$mockitoInline")
68+
testImplementation("io.mockk:mockk:${mockkVersion}")
6069
}
6170

6271
tasks {
@@ -66,5 +75,12 @@ tasks {
6675

6776
test {
6877
useJUnitPlatform()
78+
jvmArgs("-XX:+EnableDynamicAgentLoading", "-Xshare:off")
79+
}
80+
}
81+
82+
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
83+
kotlinOptions {
84+
jvmTarget = "17"
6985
}
7086
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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;
19+
20+
import com.lambda.Lambda;
21+
import com.lambda.module.Module;
22+
import com.lambda.module.ModuleRegistry;
23+
import com.lambda.util.DynamicException;
24+
import net.minecraft.client.MinecraftClient;
25+
import net.minecraft.util.Util;
26+
import net.minecraft.util.crash.CrashReport;
27+
import org.spongepowered.asm.mixin.Final;
28+
import org.spongepowered.asm.mixin.Mixin;
29+
import org.spongepowered.asm.mixin.Mutable;
30+
import org.spongepowered.asm.mixin.Shadow;
31+
import org.spongepowered.asm.mixin.injection.At;
32+
import org.spongepowered.asm.mixin.injection.Inject;
33+
import org.spongepowered.asm.mixin.injection.Redirect;
34+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
35+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
36+
37+
// Modify the crash report behavior for dynamic remapping, Easter egg and github issue link
38+
@Mixin(CrashReport.class)
39+
public class CrashReportMixin {
40+
@Mutable
41+
@Shadow @Final private Throwable cause;
42+
43+
@Inject(method = "<init>(Ljava/lang/String;Ljava/lang/Throwable;)V", at = @At("TAIL"))
44+
void injectConstructor(String message, Throwable cause, CallbackInfo ci) {
45+
if (!Lambda.INSTANCE.isDebug() && MinecraftClient.getInstance() != null) {
46+
this.cause = new DynamicException(cause);
47+
}
48+
}
49+
50+
@Redirect(method = "asString()Ljava/lang/String;", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/crash/CrashReport;addStackTrace(Ljava/lang/StringBuilder;)V"))
51+
void injectString(CrashReport instance, StringBuilder stringBuilder) {
52+
stringBuilder.append("If this issue is related to Lambda, check if other users have experienced this too, or create a new issue at https://github.com/lambda-client/lambda/issues.\n\n");
53+
54+
if (MinecraftClient.getInstance() != null) {
55+
stringBuilder.append("Enabled modules:\n");
56+
57+
ModuleRegistry.INSTANCE.getModules()
58+
.stream().filter(Module::isEnabled)
59+
.forEach(m -> stringBuilder.append("\t").append(m.getName()).append("\n"));
60+
}
61+
62+
stringBuilder.append("\n");
63+
stringBuilder.append("-".repeat(43));
64+
stringBuilder.append("\n\n");
65+
66+
instance.addStackTrace(stringBuilder);
67+
}
68+
69+
@Inject(method = "generateWittyComment()Ljava/lang/String;", at = @At("HEAD"), cancellable = true)
70+
private static void generateWittyComment(CallbackInfoReturnable<String> cir) {
71+
String[] strings = new String[]{"Who set us up the TNT?", "Everything's going to plan. No, really, that was supposed to happen.", "Uh... Did I do that?", "Oops.", "Why did you do that?", "I feel sad now :(", "My bad.", "I'm sorry, Dave.", "I let you down. Sorry :(", "On the bright side, I bought you a teddy bear!", "Daisy, daisy...", "Oh - I know what I did wrong!", "Hey, that tickles! Hehehe!", "I blame Dinnerbone.", "You should try our sister game, Minceraft!", "Don't be sad. I'll do better next time, I promise!", "Don't be sad, have a hug! <3", "I just don't know what went wrong :(", "Shall we play a game?", "Quite honestly, I wouldn't worry myself about that.", "I bet Cylons wouldn't have this problem.", "Sorry :(", "Surprise! Haha. Well, this is awkward.", "Would you like a cupcake?", "Hi. I'm Minecraft, and I'm a crashaholic.", "Ooh. Shiny.", "This doesn't make any sense!", "Why is it breaking :(", "Don't do that.", "Ouch. That hurt :(", "You're mean.", "This is a token for 1 free hug. Redeem at your nearest Mojangsta: [~~HUG~~]", "There are four lights!", "But it works on my machine.", "Popbob was here.", "The oldest anarchy server in Minecraft.", "Better luck next time..", "Fatal error occurred user is too based.", "Running premium software on a potato is not advised", "I don't know, ask that kilab guy", "Ah shit, here we go again.", "I will uhh, fix that sometime.", "Not a bug, a feature!", "You should try out Lambda on Windows XP.", "Blade did that."};
72+
73+
try {
74+
cir.setReturnValue(strings[(int)(Util.getMeasuringTimeNano() % (long)strings.length)]);
75+
} catch (Throwable var2) {
76+
cir.setReturnValue("Witty comment unavailable :(");
77+
}
78+
}
79+
}

common/src/main/java/com/lambda/mixin/MinecraftClientMixin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import net.minecraft.client.gui.screen.Screen;
2828
import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider;
2929
import net.minecraft.client.network.ClientPlayerInteractionManager;
30+
import net.minecraft.util.thread.ThreadExecutor;
3031
import org.jetbrains.annotations.Nullable;
3132
import org.spongepowered.asm.mixin.Mixin;
3233
import org.spongepowered.asm.mixin.Shadow;
@@ -67,7 +68,7 @@ private void onShutdown(CallbackInfo ci) {
6768
}
6869

6970
/**
70-
* Inject after the thread field is set so `ThreadExecutor#getThread` is available
71+
* Inject after the thread field is set so that {@link ThreadExecutor#getThread} is available
7172
*/
7273
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;thread:Ljava/lang/Thread;", shift = At.Shift.AFTER, ordinal = 0), method = "run")
7374
private void onStartup(CallbackInfo ci) {

common/src/main/java/com/lambda/mixin/entity/ClientPlayInteractionManagerMixin.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import net.minecraft.entity.Entity;
2626
import net.minecraft.entity.player.PlayerEntity;
2727
import net.minecraft.entity.player.PlayerInventory;
28+
import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
2829
import net.minecraft.screen.slot.SlotActionType;
2930
import net.minecraft.util.ActionResult;
3031
import net.minecraft.util.Hand;
@@ -86,6 +87,18 @@ public void clickSlotHead(int syncId, int slotId, int button, SlotActionType act
8687
if (EventFlow.post(click).isCanceled()) ci.cancel();
8788
}
8889

90+
/**
91+
* Posts {@link InventoryEvent.HotbarSlot.Update} and returns the event value as the selected slot
92+
* <pre>{@code
93+
* private void syncSelectedSlot() {
94+
* int i = this.client.player.getInventory().selectedSlot;
95+
* if (i != this.lastSelectedSlot) {
96+
* this.lastSelectedSlot = i;
97+
* this.networkHandler.sendPacket(new UpdateSelectedSlotC2SPacket(this.lastSelectedSlot));
98+
* }
99+
* }
100+
* }</pre>
101+
*/
89102
@Redirect(method = "syncSelectedSlot", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/player/PlayerInventory;selectedSlot:I"))
90103
public int overrideSelectedSlotSync(PlayerInventory instance) {
91104
return EventFlow.post(new InventoryEvent.HotbarSlot.Update(instance.selectedSlot)).getSlot();

0 commit comments

Comments
 (0)