2222import java .util .Set ;
2323import java .util .UUID ;
2424import java .util .LinkedHashSet ;
25+ import java .nio .charset .StandardCharsets ;
2526import java .lang .reflect .Method ;
2627import net .minecraft .client .gui .screens .Screen ;
2728import net .minecraft .client .player .LocalPlayer ;
4647import net .minecraft .world .item .enchantment .Enchantment ;
4748import net .minecraft .world .item .enchantment .ItemEnchantments ;
4849import net .minecraft .world .level .block .entity .BlockEntity ;
50+ import net .minecraft .world .level .block .entity .ShelfBlockEntity ;
4951import net .minecraft .world .level .block .entity .SignBlockEntity ;
5052import net .minecraft .world .level .block .entity .SignText ;
5153import net .minecraft .world .phys .Vec3 ;
6971import it .unimi .dsi .fastutil .objects .Object2IntMap ;
7072// no screen import needed; we embed ItemESP's editor component directly
7173import net .wurstclient .util .InventoryUtils ;
74+ import net .wurstclient .util .ShelfUtils ;
7275import net .wurstclient .util .chunk .ChunkUtils ;
7376
7477public class ItemHandlerHack extends Hack
@@ -591,6 +594,8 @@ private void scanNearbyItems()
591594 distance , frame .position (), SourceType .ITEM_FRAME , null ));
592595 }
593596
597+ addTrackedShelfItems (player , scanRadius );
598+
594599 if (includeMobEquipment .isChecked ())
595600 addMobEquipmentItems (player , scanRadius );
596601
@@ -600,6 +605,43 @@ private void scanNearbyItems()
600605 // manual toggling should untrace.)
601606 }
602607
608+ private void addTrackedShelfItems (LocalPlayer player , double scanRadius )
609+ {
610+ Vec3 playerPos = player .position ();
611+ double scanRadiusSq =
612+ scanRadius >= INFINITE_SCAN_RADIUS ? -1 : scanRadius * scanRadius ;
613+
614+ ChunkUtils .getLoadedBlockEntities ().forEach (be -> {
615+ if (!(be instanceof ShelfBlockEntity shelf ))
616+ return ;
617+
618+ Vec3 shelfCenter = shelf .position ();
619+ if (scanRadiusSq >= 0
620+ && shelfCenter .distanceToSqr (playerPos ) > scanRadiusSq )
621+ return ;
622+
623+ BlockPos shelfPos = shelf .getBlockPos ();
624+ List <ItemStack > shelfItems = shelf .getItems ();
625+ for (int slot = 0 ; slot < shelfItems .size (); slot ++)
626+ {
627+ ItemStack stack = shelfItems .get (slot );
628+ if (stack == null || stack .isEmpty ())
629+ continue ;
630+ if (isIgnoredByItemEsp (stack ))
631+ continue ;
632+
633+ Vec3 itemPos = ShelfUtils .getItemPosition (shelf , slot );
634+ if (itemPos == null )
635+ itemPos = shelfCenter ;
636+ double distance = itemPos .distanceTo (playerPos );
637+ trackedItems
638+ .add (new GroundItem (getShelfSlotEntityId (shelfPos , slot ),
639+ getShelfSlotUuid (shelfPos , slot ), stack .copy (),
640+ distance , itemPos , SourceType .SHELF , null ));
641+ }
642+ });
643+ }
644+
603645 private void scanNearbySigns ()
604646 {
605647 boolean guiOpen = MC .gui .screen () instanceof ItemHandlerScreen ;
@@ -1348,6 +1390,8 @@ public String traceId()
13481390 }
13491391 if (sourceType == SourceType .ITEM_FRAME )
13501392 return baseId + ":item_frame" ;
1393+ if (sourceType == SourceType .SHELF )
1394+ return baseId + ":shelf" ;
13511395 return baseId ;
13521396 }
13531397
@@ -1359,6 +1403,8 @@ public String sourceLabel()
13591403 return "worn by " + (sourceName != null ? sourceName : "mob" );
13601404 if (sourceType == SourceType .ITEM_FRAME )
13611405 return "in item frame" ;
1406+ if (sourceType == SourceType .SHELF )
1407+ return "in shelf" ;
13621408 return "" ;
13631409 }
13641410
@@ -1541,10 +1587,26 @@ public enum SourceType
15411587 GROUND ,
15421588 XP_ORB ,
15431589 ITEM_FRAME ,
1590+ SHELF ,
15441591 MOB_HELD ,
15451592 MOB_WORN
15461593 }
15471594
1595+ private static int getShelfSlotEntityId (BlockPos pos , int slot )
1596+ {
1597+ int hash = Long
1598+ .hashCode (pos .asLong () ^ ((long )slot + 1L ) * 0x9E3779B97F4A7C15L );
1599+ if (hash == 0 )
1600+ return Integer .MIN_VALUE ;
1601+ return hash > 0 ? -hash : hash ;
1602+ }
1603+
1604+ private static UUID getShelfSlotUuid (BlockPos pos , int slot )
1605+ {
1606+ String key = "shelf:" + pos .asLong () + ":" + slot ;
1607+ return UUID .nameUUIDFromBytes (key .getBytes (StandardCharsets .UTF_8 ));
1608+ }
1609+
15481610 private static String getCraftedEntityTraceId (UUID uuid )
15491611 {
15501612 if (uuid == null )
0 commit comments