66package meteordevelopment .meteorclient .systems .modules .player ;
77
88import meteordevelopment .meteorclient .events .world .TickEvent ;
9- import meteordevelopment .meteorclient .mixin .ItemStackAccessor ;
109import meteordevelopment .meteorclient .settings .*;
1110import meteordevelopment .meteorclient .systems .modules .Categories ;
1211import meteordevelopment .meteorclient .systems .modules .Module ;
1312import meteordevelopment .meteorclient .systems .modules .Modules ;
1413import meteordevelopment .meteorclient .systems .modules .combat .AutoTotem ;
1514import meteordevelopment .meteorclient .utils .player .InvUtils ;
16- import meteordevelopment .meteorclient .utils .player .SlotUtils ;
1715import meteordevelopment .orbit .EventHandler ;
1816import net .minecraft .item .Item ;
1917import net .minecraft .item .ItemStack ;
2018import net .minecraft .item .Items ;
2119
20+ import java .util .Arrays ;
2221import java .util .List ;
2322
2423public class AutoReplenish extends Module {
2524 private final SettingGroup sgGeneral = settings .getDefaultGroup ();
2625
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 ." )
3029 .defaultValue (8 )
3130 .min (1 )
3231 .sliderRange (1 , 63 )
@@ -35,47 +34,59 @@ public class AutoReplenish extends Module {
3534
3635 private final Setting <Integer > tickDelay = sgGeneral .add (new IntSetting .Builder ()
3736 .name ("delay" )
38- .description ("The tick delay to replenish your hotbar." )
37+ .description ("How long in ticks to wait between replenishing your hotbar." )
3938 .defaultValue (1 )
4039 .min (0 )
4140 .build ()
4241 );
4342
4443 private final Setting <Boolean > offhand = sgGeneral .add (new BoolSetting .Builder ()
4544 .name ("offhand" )
46- .description ("Whether or not to refill your offhand with items ." )
45+ .description ("Whether or not to replenish items in your offhand ." )
4746 .defaultValue (true )
4847 .build ()
4948 );
5049
5150 private final Setting <Boolean > unstackable = sgGeneral .add (new BoolSetting .Builder ()
5251 .name ("unstackable" )
53- .description ("Replenishes unstackable items." )
52+ .description ("Replenish unstackable items." )
5453 .defaultValue (true )
5554 .build ()
5655 );
5756
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+
5865 private final Setting <Boolean > searchHotbar = sgGeneral .add (new BoolSetting .Builder ()
5966 .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 )
6269 .build ()
6370 );
6471
6572 private final Setting <List <Item >> excludedItems = sgGeneral .add (new ItemListSetting .Builder ()
6673 .name ("excluded-items" )
67- .description ("Items that WILL NOT replenish ." )
74+ .description ("Items that won't be replenished ." )
6875 .build ()
6976 );
7077
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+ */
7182 private final ItemStack [] items = new ItemStack [10 ];
7283 private boolean prevHadOpenScreen ;
7384 private int tickDelayLeft ;
7485
7586 public AutoReplenish () {
7687 super (Categories .Player , "auto-replenish" , "Automatically refills items in your hotbar, main hand, or offhand." );
7788
78- for ( int i = 0 ; i < items . length ; i ++) items [ i ] = new ItemStack ( Items .AIR );
89+ Arrays . fill ( items , Items .AIR . getDefaultStack () );
7990 }
8091
8192 @ Override
@@ -94,97 +105,83 @@ private void onTick(TickEvent.Pre event) {
94105 prevHadOpenScreen = mc .currentScreen != null ;
95106 if (mc .player .currentScreenHandler .getStacks ().size () != 46 || mc .currentScreen != null ) return ;
96107
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+ }
105112
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 );
111117 }
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 );
114123 }
124+
125+ tickDelayLeft = tickDelay .get ();
115126 }
116127
117128 private void checkSlot (int slot , ItemStack stack ) {
118- ItemStack prevStack = getItem (slot );
129+ ItemStack prevStack = items [slot ];
130+ items [slot ] = stack .copy ();
119131
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 );
125140 }
126141
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 );
138147 }
139148
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 );
141155 }
142156
143- private int findItem (ItemStack itemStack , int excludedSlot , int goodEnoughCount ) {
157+ private int findItem (ItemStack lookForStack , int excludedSlot , int goodEnoughCount ) {
144158 int slot = -1 ;
145159 int count = 0 ;
146160
147161 for (int i = mc .player .getInventory ().size () - 2 ; i >= (searchHotbar .get () ? 0 : 9 ); i --) {
162+ if (i == excludedSlot ) continue ;
163+
148164 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 ;
149168
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 ();
154172
155- if (count >= goodEnoughCount ) break ;
156- }
173+ if (count >= goodEnoughCount ) break ;
157174 }
158175 }
159176
160177 return slot ;
161178 }
162179
163- private void addSlots (int to , int from ) {
164- InvUtils .move ().from (from ).to (to );
165- }
166-
167180 private void fillItems () {
168181 for (int i = 0 ; i < 9 ; i ++) {
169- setItem ( i , mc .player .getInventory ().getStack (i ));
182+ items [ i ] = mc .player .getInventory ().getStack (i ). copy ( );
170183 }
171184
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 ();
189186 }
190187}
0 commit comments