6
6
package meteordevelopment .meteorclient .systems .modules .player ;
7
7
8
8
import meteordevelopment .meteorclient .events .world .TickEvent ;
9
- import meteordevelopment .meteorclient .mixin .ItemStackAccessor ;
10
9
import meteordevelopment .meteorclient .settings .*;
11
10
import meteordevelopment .meteorclient .systems .modules .Categories ;
12
11
import meteordevelopment .meteorclient .systems .modules .Module ;
13
12
import meteordevelopment .meteorclient .systems .modules .Modules ;
14
13
import meteordevelopment .meteorclient .systems .modules .combat .AutoTotem ;
15
14
import meteordevelopment .meteorclient .utils .player .InvUtils ;
16
- import meteordevelopment .meteorclient .utils .player .SlotUtils ;
17
15
import meteordevelopment .orbit .EventHandler ;
18
16
import net .minecraft .item .Item ;
19
17
import net .minecraft .item .ItemStack ;
20
18
import net .minecraft .item .Items ;
21
19
20
+ import java .util .Arrays ;
22
21
import java .util .List ;
23
22
24
23
public class AutoReplenish extends Module {
25
24
private final SettingGroup sgGeneral = settings .getDefaultGroup ();
26
25
27
- private final Setting <Integer > threshold = sgGeneral .add (new IntSetting .Builder ()
28
- .name ("threshold " )
29
- .description ("The threshold of items left this actives at ." )
26
+ private final Setting <Integer > minCount = sgGeneral .add (new IntSetting .Builder ()
27
+ .name ("min-count " )
28
+ .description ("Replenish a slot when it reaches this item count ." )
30
29
.defaultValue (8 )
31
30
.min (1 )
32
31
.sliderRange (1 , 63 )
@@ -35,47 +34,59 @@ public class AutoReplenish extends Module {
35
34
36
35
private final Setting <Integer > tickDelay = sgGeneral .add (new IntSetting .Builder ()
37
36
.name ("delay" )
38
- .description ("The tick delay to replenish your hotbar." )
37
+ .description ("How long in ticks to wait between replenishing your hotbar." )
39
38
.defaultValue (1 )
40
39
.min (0 )
41
40
.build ()
42
41
);
43
42
44
43
private final Setting <Boolean > offhand = sgGeneral .add (new BoolSetting .Builder ()
45
44
.name ("offhand" )
46
- .description ("Whether or not to refill your offhand with items ." )
45
+ .description ("Whether or not to replenish items in your offhand ." )
47
46
.defaultValue (true )
48
47
.build ()
49
48
);
50
49
51
50
private final Setting <Boolean > unstackable = sgGeneral .add (new BoolSetting .Builder ()
52
51
.name ("unstackable" )
53
- .description ("Replenishes unstackable items." )
52
+ .description ("Replenish unstackable items." )
54
53
.defaultValue (true )
55
54
.build ()
56
55
);
57
56
57
+ private final Setting <Boolean > sameEnchants = sgGeneral .add (new BoolSetting .Builder ()
58
+ .name ("same-enchants" )
59
+ .description ("Only replace unstackables with items that have the same enchants." )
60
+ .defaultValue (true )
61
+ .visible (unstackable ::get )
62
+ .build ()
63
+ );
64
+
58
65
private final Setting <Boolean > searchHotbar = sgGeneral .add (new BoolSetting .Builder ()
59
66
.name ("search-hotbar" )
60
- .description ("Uses items in your hotbar to replenish if they are the only ones left ." )
61
- .defaultValue (true )
67
+ .description ("Combine stacks in your hotbar/offhand as a last resort ." )
68
+ .defaultValue (false )
62
69
.build ()
63
70
);
64
71
65
72
private final Setting <List <Item >> excludedItems = sgGeneral .add (new ItemListSetting .Builder ()
66
73
.name ("excluded-items" )
67
- .description ("Items that WILL NOT replenish ." )
74
+ .description ("Items that won't be replenished ." )
68
75
.build ()
69
76
);
70
77
78
+ /**
79
+ * Represents the items the player had last tick. Indices 0-8 represent the
80
+ * hotbar from left to right, index 9 represents the player's offhand
81
+ */
71
82
private final ItemStack [] items = new ItemStack [10 ];
72
83
private boolean prevHadOpenScreen ;
73
84
private int tickDelayLeft ;
74
85
75
86
public AutoReplenish () {
76
87
super (Categories .Player , "auto-replenish" , "Automatically refills items in your hotbar, main hand, or offhand." );
77
88
78
- for ( int i = 0 ; i < items . length ; i ++) items [ i ] = new ItemStack ( Items .AIR );
89
+ Arrays . fill ( items , Items .AIR . getDefaultStack () );
79
90
}
80
91
81
92
@ Override
@@ -94,97 +105,83 @@ private void onTick(TickEvent.Pre event) {
94
105
prevHadOpenScreen = mc .currentScreen != null ;
95
106
if (mc .player .currentScreenHandler .getStacks ().size () != 46 || mc .currentScreen != null ) return ;
96
107
97
- if (tickDelayLeft <= 0 ) {
98
- tickDelayLeft = tickDelay .get ();
99
-
100
- // Hotbar
101
- for (int i = 0 ; i < 9 ; i ++) {
102
- ItemStack stack = mc .player .getInventory ().getStack (i );
103
- checkSlot (i , stack );
104
- }
108
+ if (tickDelayLeft > 0 ) {
109
+ tickDelayLeft --;
110
+ return ;
111
+ }
105
112
106
- // Offhand
107
- if (offhand .get () && !Modules .get ().get (AutoTotem .class ).isLocked ()) {
108
- ItemStack stack = mc .player .getOffHandStack ();
109
- checkSlot (SlotUtils .OFFHAND , stack );
110
- }
113
+ // Hotbar
114
+ for (int i = 0 ; i < 9 ; i ++) {
115
+ ItemStack stack = mc .player .getInventory ().getStack (i );
116
+ checkSlot (i , stack );
111
117
}
112
- else {
113
- tickDelayLeft --;
118
+
119
+ // Offhand
120
+ if (offhand .get () && !Modules .get ().get (AutoTotem .class ).isLocked ()) {
121
+ ItemStack stack = mc .player .getOffHandStack ();
122
+ checkSlot (9 , stack );
114
123
}
124
+
125
+ tickDelayLeft = tickDelay .get ();
115
126
}
116
127
117
128
private void checkSlot (int slot , ItemStack stack ) {
118
- ItemStack prevStack = getItem (slot );
129
+ ItemStack prevStack = items [slot ];
130
+ items [slot ] = stack .copy ();
119
131
120
- // Stackable items 1
121
- if (!stack .isEmpty () && stack .isStackable () && !excludedItems .get ().contains (stack .getItem ())) {
122
- if (stack .getCount () <= threshold .get ()) {
123
- addSlots (slot , findItem (stack , slot , threshold .get () - stack .getCount () + 1 ));
124
- }
132
+ if (excludedItems .get ().contains (stack .getItem ())) return ;
133
+ if (excludedItems .get ().contains (prevStack .getItem ())) return ;
134
+
135
+ int fromSlot = -1 ;
136
+
137
+ // If there are still items left in the stack, but it just crossed the threshold
138
+ if (stack .isStackable () && !stack .isEmpty () && stack .getCount () <= minCount .get ()) {
139
+ fromSlot = findItem (stack , slot , minCount .get () - stack .getCount () + 1 );
125
140
}
126
141
127
- if (stack .isEmpty () && !prevStack .isEmpty () && !excludedItems .get ().contains (prevStack .getItem ())) {
128
- // Stackable items 2
129
- if (prevStack .isStackable ()) {
130
- addSlots (slot , findItem (prevStack , slot , threshold .get () - stack .getCount () + 1 ));
131
- }
132
- // Unstackable items
133
- else {
134
- if (unstackable .get ()) {
135
- addSlots (slot , findItem (prevStack , slot , 1 ));
136
- }
137
- }
142
+ // If the stack just went from above the threshold to empty in a single tick
143
+ // this can happen if the threshold is set low enough while using modules that
144
+ // place many blocks per tick, like surround or holefiller
145
+ if (prevStack .isStackable () && stack .isEmpty () && !prevStack .isEmpty ()) {
146
+ fromSlot = findItem (prevStack , slot , minCount .get () - stack .getCount () + 1 );
138
147
}
139
148
140
- setItem (slot , stack );
149
+ // Unstackable items
150
+ if (unstackable .get () && !prevStack .isStackable () && stack .isEmpty () && !prevStack .isEmpty ()) {
151
+ fromSlot = findItem (prevStack , slot , 1 );
152
+ }
153
+
154
+ InvUtils .move ().from (fromSlot ).to (slot );
141
155
}
142
156
143
- private int findItem (ItemStack itemStack , int excludedSlot , int goodEnoughCount ) {
157
+ private int findItem (ItemStack lookForStack , int excludedSlot , int goodEnoughCount ) {
144
158
int slot = -1 ;
145
159
int count = 0 ;
146
160
147
161
for (int i = mc .player .getInventory ().size () - 2 ; i >= (searchHotbar .get () ? 0 : 9 ); i --) {
162
+ if (i == excludedSlot ) continue ;
163
+
148
164
ItemStack stack = mc .player .getInventory ().getStack (i );
165
+ if (stack .getItem () != lookForStack .getItem ()) continue ;
166
+
167
+ if (sameEnchants .get () && !stack .getEnchantments ().equals (lookForStack .getEnchantments ())) continue ;
149
168
150
- if (i != excludedSlot && stack .getItem () == itemStack .getItem () && ItemStack .areItemsAndComponentsEqual (itemStack , stack )) {
151
- if (stack .getCount () > count ) {
152
- slot = i ;
153
- count = stack .getCount ();
169
+ if (stack .getCount () > count ) {
170
+ slot = i ;
171
+ count = stack .getCount ();
154
172
155
- if (count >= goodEnoughCount ) break ;
156
- }
173
+ if (count >= goodEnoughCount ) break ;
157
174
}
158
175
}
159
176
160
177
return slot ;
161
178
}
162
179
163
- private void addSlots (int to , int from ) {
164
- InvUtils .move ().from (from ).to (to );
165
- }
166
-
167
180
private void fillItems () {
168
181
for (int i = 0 ; i < 9 ; i ++) {
169
- setItem ( i , mc .player .getInventory ().getStack (i ));
182
+ items [ i ] = mc .player .getInventory ().getStack (i ). copy ( );
170
183
}
171
184
172
- setItem (SlotUtils .OFFHAND , mc .player .getOffHandStack ());
173
- }
174
-
175
- private ItemStack getItem (int slot ) {
176
- if (slot == SlotUtils .OFFHAND ) slot = 9 ;
177
-
178
- return items [slot ];
179
- }
180
-
181
- private void setItem (int slot , ItemStack stack ) {
182
- if (slot == SlotUtils .OFFHAND ) slot = 9 ;
183
-
184
- ItemStack s = items [slot ];
185
- ((ItemStackAccessor ) (Object ) s ).setItem (stack .getItem ());
186
- s .setCount (stack .getCount ());
187
- s .applyComponentsFrom (stack .getComponents ());
188
- if (stack .isEmpty ()) ((ItemStackAccessor ) (Object ) s ).setItem (Items .AIR );
185
+ items [9 ] = mc .player .getOffHandStack ().copy ();
189
186
}
190
187
}
0 commit comments