Skip to content

Commit ff11290

Browse files
authored
StashMover module (#282)
1 parent 6629d7b commit ff11290

24 files changed

Lines changed: 1165 additions & 96 deletions

File tree

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.lambda.core.TimerManager;
2121
import com.lambda.event.EventFlow;
2222
import com.lambda.event.events.ClientEvent;
23+
import com.lambda.event.events.GuiEvent;
2324
import com.lambda.event.events.InventoryEvent;
2425
import com.lambda.event.events.TickEvent;
2526
import com.lambda.gui.DearImGui;
@@ -205,4 +206,10 @@ void updateWindowTitle(CallbackInfo ci) {
205206
WindowUtils.setLambdaTitle();
206207
ci.cancel();
207208
}
209+
210+
@Inject(method = "setScreen", at = @At("HEAD"), cancellable = true)
211+
private void injectSetScreen(Screen screen, CallbackInfo ci) {
212+
var event = new GuiEvent.ScreenOpen(screen);
213+
if (EventFlow.post(event).isCanceled()) ci.cancel();
214+
}
208215
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import com.lambda.event.events.InventoryEvent;
2222
import com.lambda.event.events.PlayerEvent;
2323
import com.lambda.interaction.managers.inventory.InventoryManager;
24+
import com.lambda.interaction.managers.rotating.RotationManager;
25+
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
2426
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
2527
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
2628
import net.minecraft.client.network.ClientPlayerEntity;
@@ -73,6 +75,18 @@ public void interactItemHead(PlayerEntity player, Hand hand, CallbackInfoReturna
7375
}
7476
}
7577

78+
@ModifyExpressionValue(method = "method_41929", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;getYaw()F"))
79+
private float modifyHand(float original) {
80+
var headYaw = RotationManager.getHeadYaw();
81+
return headYaw != null ? headYaw : original;
82+
}
83+
84+
@ModifyExpressionValue(method = "method_41929", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;getPitch()F"))
85+
private float modifySequence(float original) {
86+
var headPitch = RotationManager.getHeadPitch();
87+
return headPitch != null ? headPitch : original;
88+
}
89+
7690
@Inject(method = "attackBlock", at = @At("HEAD"), cancellable = true)
7791
public void onAttackBlock(BlockPos pos, Direction side, CallbackInfoReturnable<Boolean> cir) {
7892
if (EventFlow.post(new PlayerEvent.Attack.Block(pos, side)).isCanceled()) {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2026 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.argument.literal
21+
import com.lambda.brigadier.execute
22+
import com.lambda.brigadier.required
23+
import com.lambda.command.LambdaCommand
24+
import com.lambda.module.modules.world.StashMover
25+
import com.lambda.threading.runSafe
26+
import com.lambda.util.extension.CommandBuilder
27+
28+
object StashMoverCommand : LambdaCommand(
29+
name = "stashmover",
30+
usage = "stashmover <command>",
31+
description = "Set configurations for the StashMover module"
32+
) {
33+
override fun CommandBuilder.create() {
34+
required(literal("index_selected_containers")) {
35+
execute { runSafe { StashMover.indexSelectedContainers() } }
36+
}
37+
required(literal("remove_selected_containers")) {
38+
execute { runSafe { StashMover.removeSelectedContainers() } }
39+
}
40+
required(literal("set_item_throw")) {
41+
execute { runSafe { StashMover.setItemThrow() } }
42+
}
43+
required(literal("set_pearl_button_pos")) {
44+
execute { runSafe { StashMover.setPearlButtonPos() } }
45+
}
46+
required(literal("set_pearl_throw")) {
47+
execute { runSafe { StashMover.setPearlThrow() } }
48+
}
49+
required(literal("set_pearlbot_button")) {
50+
execute { runSafe { StashMover.setPearlBotButton() } }
51+
}
52+
required(literal("start-stop")) {
53+
execute { runSafe { StashMover.startStop() } }
54+
}
55+
required(literal("pause-unpause")) {
56+
execute { runSafe { StashMover.pauseUnpause() } }
57+
}
58+
}
59+
}

src/main/kotlin/com/lambda/config/groups/BuildConfig.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ interface BuildConfig : ISettingGroup {
3636
val maxBuildDependencies: Int
3737

3838
val limitTimeframe: Int
39-
val actionPacketLimit: Int
40-
val interactionPacketLimit: Int
39+
val actionLimit: Int
40+
val interactionLimit: Int
41+
val inventoryLimit: Int
4142

4243
val blockReach: Double
4344
val entityReach: Double

src/main/kotlin/com/lambda/config/groups/BuildSettings.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ class BuildSettings(
4848
override val actionTimeout by c.setting("${prefix}Action Timeout", 10, 1..30, 1, "Timeout for block breaks in ticks", unit = " ticks", visibility = visibility).group(*baseGroup, Group.General).index()
4949
override val maxBuildDependencies by c.setting("${prefix}Max Sim Dependencies", 3, 0..10, 1, "Maximum dependency build results", visibility = visibility).group(*baseGroup, Group.General).index()
5050

51-
override val limitTimeframe by c.setting("${prefix}Limit Timeframe", 6, 1..30, 1, "The timeframe in which the limit is bound to", "ticks", visibility = visibility).group(*baseGroup, Group.PacketLimits).index()
52-
override val actionPacketLimit by c.setting("${prefix}Action Packet Limit", 55, 1..100, 1, "The maximum allowed action packets to be sent to the server per given timeframe", visibility = visibility).group(*baseGroup, Group.PacketLimits).index()
53-
override val interactionPacketLimit by c.setting("Interaction Limit", 9, 1..20, 1, "The maximum allowed interaction packets to be sent to the server per given timeframe", visibility = visibility).group(*baseGroup, Group.PacketLimits).index()
51+
override val limitTimeframe by c.setting("${prefix}Limit Timeframe", 310, 50..1500, 1, "The timeframe in which the limit is bound to", "ms", visibility = visibility).group(*baseGroup, Group.PacketLimits).index()
52+
override val actionLimit by c.setting("${prefix}Action Limit", 59, 1..100, 1, "The maximum allowed action packets to be sent to the server per given timeframe", visibility = visibility).group(*baseGroup, Group.PacketLimits).index()
53+
override val interactionLimit by c.setting("${prefix}Interaction Limit", 9, 1..20, 1, "The maximum allowed interaction packets to be sent to the server per given timeframe", visibility = visibility).group(*baseGroup, Group.PacketLimits).index()
54+
override val inventoryLimit by c.setting("${prefix}Inventory Limit", 5, 1..100, 1, "The maximum allowed inventory packets to be sent to the server per given timeframe", visibility = visibility).group(*baseGroup, Group.PacketLimits).index()
5455

5556
override var blockReach by c.setting("${prefix}Interact Reach", 4.5, 1.0..7.0, 0.01, "Maximum block interaction distance", visibility = visibility).group(*baseGroup, Group.Reach).index()
5657
override var entityReach by c.setting("${prefix}Attack Reach", 3.0, 1.0..7.0, 0.01, "Maximum entity interaction distance", visibility = visibility).group(*baseGroup, Group.Reach).index()

src/main/kotlin/com/lambda/config/groups/InventorySettings.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class InventorySettings(
3636
Access("Access")
3737
}
3838

39-
override val actionsPerSecond by c.setting("${prefix}Actions Per Second", 100, 0..100, 1, "How many inventory actions can be performed per tick", visibility = visibility).group(*baseGroup, Group.General).index()
4039
override val tickStageMask by c.setting("${prefix}Inventory Stage Mask", ALL_STAGES.toSet(), description = "The sub-tick timing at which inventory actions are performed", displayClassName = true, visibility = visibility).group(*baseGroup, Group.General).index()
4140
override val disposables by c.setting("${prefix}Disposables", ItemUtils.defaultDisposables, description = "Items that will be ignored when checking for a free slot", visibility = visibility).group(*baseGroup, Group.Container).index()
4241
override val swapWithDisposables by c.setting("${prefix}Swap With Disposables", true, "Swap items with disposable ones", visibility = visibility).group(*baseGroup, Group.Container).index()
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2026 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.migration.migrations
19+
20+
import com.lambda.Lambda.LOG
21+
import com.lambda.config.migration.StepConfigMigration
22+
23+
object AutomationConfigMigration : StepConfigMigration() {
24+
override val configName = "automation"
25+
override val latestVersion = 2
26+
27+
init {
28+
step(1, 2) {
29+
var updateCount = 0
30+
entrySet().forEach { configPair ->
31+
getAsJsonObject(configPair.key)?.let { config ->
32+
config.get("Limit Timeframe")?.let { limitTimeframe ->
33+
if (limitTimeframe.asInt < 50) {
34+
config.addProperty("Limit Timeframe", 310)
35+
updateCount++
36+
}
37+
}
38+
}
39+
}
40+
41+
LOG.info("Migrated Automation config schema v1 -> v2: $updateCount settings updated")
42+
}
43+
}
44+
}

src/main/kotlin/com/lambda/event/events/GuiEvent.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,22 @@ import com.lambda.event.Event
2121
import com.lambda.event.callback.Cancellable
2222
import com.lambda.event.callback.ICancellable
2323
import net.minecraft.block.entity.SignBlockEntity
24+
import net.minecraft.client.gui.screen.Screen
2425

2526
sealed class GuiEvent {
2627
/**
2728
* Triggered when a new ImGui frame is created and the client
28-
* is allowed to submit any command from this point until [EndFrame].
29+
* is allowed to submit any command from this point until [EndImguiFrame].
2930
*/
30-
data object NewFrame : Event
31+
data object NewImguiFrame : Event
3132

3233
/**
3334
* Triggered when the previous ImGui frame is ended and the client
3435
* is able to perform OpenGL calls.
3536
*
3637
* By default, the game's framebuffer is bound.
3738
*/
38-
data object EndFrame : Event
39+
data object EndImguiFrame : Event
3940

4041
/**
4142
* Triggered when the sign editor GUI is opened. Can be canceled.
@@ -44,4 +45,6 @@ sealed class GuiEvent {
4445
var sign: SignBlockEntity,
4546
var front: Boolean
4647
) : ICancellable by Cancellable()
48+
49+
data class ScreenOpen(val screen: Screen?) : ICancellable by Cancellable()
4750
}

src/main/kotlin/com/lambda/gui/DearImGui.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ object DearImGui : Loadable {
116116
ClickGuiLayout.applyStyle(lastScale)
117117
ImGui.newFrame()
118118

119-
GuiEvent.NewFrame.post()
119+
GuiEvent.NewImguiFrame.post()
120120
ImGui.render()
121-
GuiEvent.EndFrame.post()
121+
GuiEvent.EndImguiFrame.post()
122122

123123
implGl3.renderDrawData(ImGui.getDrawData())
124124

src/main/kotlin/com/lambda/gui/components/ClickGuiLayout.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ object ClickGuiLayout : Loadable, Configurable(GuiConfig) {
244244
val modalWindowDimBg by setting("Modal Window Dim Background", Color(35, 0, 14, 90)).group(Group.Colors)
245245

246246
init {
247-
listen<GuiEvent.NewFrame> {
247+
listen<GuiEvent.NewImguiFrame> {
248248
if (!open) return@listen
249249

250250
buildLayout {

0 commit comments

Comments
 (0)