@@ -148,6 +148,11 @@ public class ItemHandlerHack extends Hack
148148 new CheckboxSetting ("Detect named entities" ,
149149 "Detects custom-named entities (e.g. pets and mobs)." , false );
150150
151+ private final CheckboxSetting detectCraftedEntities = new CheckboxSetting (
152+ "Detect crafted entities" ,
153+ "Detects nearby crafted entities like boats/rafts, paintings, glow item frames, and selected minecarts." ,
154+ false );
155+
151156 private final SliderSetting signRange = new SliderSetting ("Sign range" ,
152157 "How far to scan for signs when 'Show nearby signs' is enabled.\n "
153158 + "∞ = all loaded chunks around you (limited by render distance)." ,
@@ -211,6 +216,7 @@ public ItemHandlerHack()
211216 addSetting (pinSpecialItemsTop );
212217 addSetting (showSignsInHud );
213218 addSetting (detectNamedEntities );
219+ addSetting (detectCraftedEntities );
214220 addSetting (respectItemEspIgnores );
215221 addSetting (itemEspIgnoredListSetting );
216222 addSetting (rejectRadius );
@@ -589,7 +595,8 @@ private void scanNearbySigns()
589595 boolean guiOpen = MC .screen instanceof ItemHandlerScreen ;
590596 boolean detectSigns = showSignsInHud .isChecked () || guiOpen ;
591597 boolean detectNamed = detectNamedEntities .isChecked () || guiOpen ;
592- if (!detectSigns && !detectNamed )
598+ boolean detectCrafted = detectCraftedEntities .isChecked () || guiOpen ;
599+ if (!detectSigns && !detectNamed && !detectCrafted )
593600 {
594601 trackedLabels .clear ();
595602 return ;
@@ -660,6 +667,28 @@ private void scanNearbySigns()
660667 }
661668 }
662669
670+ if (detectCrafted )
671+ {
672+ AABB scanBox = MC .player .getBoundingBox ().inflate (range );
673+ List <Entity > craftedEntities = MC .level .getEntities (MC .player ,
674+ scanBox , e -> e != null && e .isAlive () && !e .isRemoved ()
675+ && isTrackedCraftedEntityType (e ));
676+
677+ for (Entity entity : craftedEntities )
678+ {
679+ Vec3 p = entity .position ();
680+ double distSq = p .distanceToSqr (centerVec );
681+ if (!infinite && distSq > rangeSq )
682+ continue ;
683+
684+ ItemStack icon = iconForCraftedEntity (entity );
685+ String label = "Crafted entity: " + craftedEntityLabel (entity );
686+ trackedLabels .add (new NearbyLabel (p , entity .getBoundingBox (),
687+ icon , label , Math .sqrt (distSq ),
688+ getCraftedEntityTraceId (entity .getUUID ())));
689+ }
690+ }
691+
663692 trackedLabels
664693 .sort (java .util .Comparator .comparingDouble (NearbyLabel ::distance ));
665694
@@ -1458,6 +1487,83 @@ public enum SourceType
14581487 MOB_WORN
14591488 }
14601489
1490+ private static String getCraftedEntityTraceId (UUID uuid )
1491+ {
1492+ if (uuid == null )
1493+ return null ;
1494+ return "crafted_entity:" + uuid ;
1495+ }
1496+
1497+ private boolean isTrackedCraftedEntityType (Entity entity )
1498+ {
1499+ if (entity == null )
1500+ return false ;
1501+
1502+ String path =
1503+ net .minecraft .core .registries .BuiltInRegistries .ENTITY_TYPE
1504+ .getKey (entity .getType ()).getPath ();
1505+ return path .endsWith ("_boat" ) || path .endsWith ("_chest_boat" )
1506+ || path .equals ("bamboo_raft" ) || path .equals ("bamboo_chest_raft" )
1507+ || path .equals ("painting" ) || path .equals ("glow_item_frame" )
1508+ || path .equals ("furnace_minecart" ) || path .equals ("hopper_minecart" )
1509+ || path .equals ("tnt_minecart" );
1510+ }
1511+
1512+ private ItemStack iconForCraftedEntity (Entity entity )
1513+ {
1514+ if (entity == null )
1515+ return new ItemStack (Items .NAME_TAG );
1516+
1517+ String path =
1518+ net .minecraft .core .registries .BuiltInRegistries .ENTITY_TYPE
1519+ .getKey (entity .getType ()).getPath ();
1520+ if (path .endsWith ("_boat" ) || path .equals ("bamboo_raft" )
1521+ || path .equals ("bamboo_chest_raft" ))
1522+ return new ItemStack (Items .OAK_BOAT );
1523+ if (path .endsWith ("_chest_boat" ))
1524+ return new ItemStack (Items .OAK_CHEST_BOAT );
1525+ if (path .equals ("painting" ))
1526+ return new ItemStack (Items .PAINTING );
1527+ if (path .equals ("glow_item_frame" ))
1528+ return new ItemStack (Items .GLOW_ITEM_FRAME );
1529+ if (path .equals ("furnace_minecart" ))
1530+ return new ItemStack (Items .FURNACE_MINECART );
1531+ if (path .equals ("hopper_minecart" ))
1532+ return new ItemStack (Items .HOPPER_MINECART );
1533+ if (path .equals ("tnt_minecart" ))
1534+ return new ItemStack (Items .TNT_MINECART );
1535+
1536+ return new ItemStack (Items .NAME_TAG );
1537+ }
1538+
1539+ private String craftedEntityLabel (Entity entity )
1540+ {
1541+ if (entity == null )
1542+ return "entity" ;
1543+
1544+ String path =
1545+ net .minecraft .core .registries .BuiltInRegistries .ENTITY_TYPE
1546+ .getKey (entity .getType ()).getPath ();
1547+ return switch (path )
1548+ {
1549+ case "bamboo_raft" -> "Bamboo raft" ;
1550+ case "bamboo_chest_raft" -> "Bamboo chest raft" ;
1551+ case "painting" -> "Painting" ;
1552+ case "glow_item_frame" -> "Glow item frame" ;
1553+ case "furnace_minecart" -> "Minecart with furnace" ;
1554+ case "hopper_minecart" -> "Minecart with hopper" ;
1555+ case "tnt_minecart" -> "Minecart with TNT" ;
1556+ default ->
1557+ {
1558+ if (path .endsWith ("_chest_boat" ))
1559+ yield "Chest boat" ;
1560+ if (path .endsWith ("_boat" ))
1561+ yield "Boat" ;
1562+ yield path .replace ('_' , ' ' );
1563+ }
1564+ };
1565+ }
1566+
14611567 // Inline ItemESP ignored-items editor in ItemHandler settings
14621568 private final Setting itemEspIgnoredListSetting =
14631569 new Setting ("Ignored items" , WText .empty ())
0 commit comments