diff --git a/src/main/java/meteordevelopment/meteorclient/systems/hud/elements/InventoryHud.java b/src/main/java/meteordevelopment/meteorclient/systems/hud/elements/InventoryHud.java index 2509cb271f..9345b07a87 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/hud/elements/InventoryHud.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/hud/elements/InventoryHud.java @@ -5,20 +5,27 @@ package meteordevelopment.meteorclient.systems.hud.elements; +import static meteordevelopment.meteorclient.MeteorClient.mc; + import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.hud.Hud; import meteordevelopment.meteorclient.systems.hud.HudElement; import meteordevelopment.meteorclient.systems.hud.HudElementInfo; import meteordevelopment.meteorclient.systems.hud.HudRenderer; +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.render.Nametags; +import meteordevelopment.meteorclient.systems.modules.render.ESP; import meteordevelopment.meteorclient.utils.Utils; import meteordevelopment.meteorclient.utils.render.color.Color; import meteordevelopment.meteorclient.utils.render.color.SettingColor; + +import net.minecraft.entity.EntityType; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.Identifier; -import static meteordevelopment.meteorclient.MeteorClient.mc; +import java.util.*; public class InventoryHud extends HudElement { public static final HudElementInfo INFO = new HudElementInfo<>(Hud.GROUP, "inventory", "Displays your inventory.", InventoryHud::new); @@ -35,13 +42,59 @@ public class InventoryHud extends HudElement { .build() ); + private final Setting isAutoconf = sgGeneral.add(new BoolSetting.Builder() + .name("autoconfigure-module") + .description("Automatically enables relevant features of a selected module") + .defaultValue(true) + .build() + ); + + private final Setting selectedSource = sgGeneral.add(new EnumSetting.Builder() + .name("selected-source") + .description("From which source to display items.") + .defaultValue(SupportedSources.Inventory) + .onChanged(source -> { + if (isAutoconf.get()) { + source.configure(); + } + }) + .build() + ); + + private int containerItemsWidth = 9; + private int containerItemsHeight = 3; + private boolean assumeDefaultSize = true; + + public final Setting sourceContainerWidth = sgGeneral.add(new IntSetting.Builder() + .name("source-container-width") + .description("Maximum width of the input container") + .defaultValue(9) + .onChanged(integer -> { + resizeContainerItems(integer, containerItemsHeight); + }) + .min(1) + .sliderRange(1, 20) + .build() + ); + + public final Setting sourceContainerHeight = sgGeneral.add(new IntSetting.Builder() + .name("source-container-height") + .description("Maximum height of the input container") + .defaultValue(3) + .onChanged(integer -> { + resizeContainerItems(containerItemsWidth, integer); + }) + .min(1) + .sliderRange(1, 20) + .build() + ); + private final Setting scale = sgGeneral.add(new DoubleSetting.Builder() .name("scale") .description("The scale.") .defaultValue(2) .min(1) .sliderRange(1, 5) - .onChanged(aDouble -> calculateSize()) .build() ); @@ -49,7 +102,6 @@ public class InventoryHud extends HudElement { .name("background") .description("Background of inventory viewer.") .defaultValue(Background.Texture) - .onChanged(bg -> calculateSize()) .build() ); @@ -61,12 +113,21 @@ public class InventoryHud extends HudElement { .build() ); - private final ItemStack[] containerItems = new ItemStack[9 * 3]; + private ArrayList containerItems = new ArrayList<>(); + void resizeContainerItems(int newWidth, int newHeight) { + int size = newWidth * newHeight; + containerItems = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + containerItems.add(null); + } + containerItemsWidth = newWidth; + containerItemsHeight = newHeight; + } private InventoryHud() { super(INFO); - calculateSize(); + resizeContainerItems(9, 3); } @Override @@ -75,9 +136,26 @@ public void render(HudRenderer renderer) { ItemStack container = getContainer(); boolean hasContainer = containers.get() && container != null; - if (hasContainer) Utils.getItemsInContainerItem(container, containerItems); - Color drawColor = hasContainer ? Utils.getShulkerColor(container) : color.get(); + if (hasContainer) { + assumeDefaultSize = true; + ItemStack[] containerItemsArray = new ItemStack[3 * 9]; + Utils.getItemsInContainerItem(container, containerItemsArray); + containerItems = new ArrayList<>(Arrays.asList(containerItemsArray)); + } + else { + assumeDefaultSize = false; + resizeContainerItems(containerItemsWidth, containerItemsHeight); + ArrayList items = selectedSource.get().getItems(); + for (int i = 0; i < containerItems.size(); ++i) { + containerItems.set(i, i < items.size() ? items.get(i) : null); + } + } + int w = (assumeDefaultSize ? 9 : containerItemsWidth); + int h = (assumeDefaultSize ? 3 : containerItemsHeight); + calculateSize(w, h); + + Color drawColor = hasContainer ? Utils.getShulkerColor(container) : color.get(); if (background.get() != Background.None) { drawBackground(renderer, (int) x, (int) y, drawColor); } @@ -85,10 +163,10 @@ public void render(HudRenderer renderer) { if (mc.player == null) return; renderer.post(() -> { - for (int row = 0; row < 3; row++) { - for (int i = 0; i < 9; i++) { - int index = row * 9 + i; - ItemStack stack = hasContainer ? containerItems[index] : mc.player.getInventory().getStack(index + 9); + for (int row = 0; row < h; row++) { + for (int i = 0; i < w; i++) { + int index = row * w + i; + ItemStack stack = containerItems.get(index); if (stack == null) continue; int itemX = background.get() == Background.Texture ? (int) (x + (8 + i * 18) * scale.get()) : (int) (x + (1 + i * 18) * scale.get()); @@ -100,18 +178,28 @@ public void render(HudRenderer renderer) { }); } - private void calculateSize() { - setSize(background.get().width * scale.get(), background.get().height * scale.get()); + private void calculateSize(int w, int h) { + if (background.get() == Background.Texture) { + setSize((8 + (w - 1) * 18 + 24) * scale.get(), (7 + (h - 1) * 18 + 24) * scale.get()); + } else { + setSize((1 + (w - 1) * 18 + 17) * scale.get(), (1 + (h - 1) * 18 + 17) * scale.get()); + } } private void drawBackground(HudRenderer renderer, int x, int y, Color color) { int w = getWidth(); int h = getHeight(); - switch (background.get()) { + // TODO: Generate Texture and Outline textures for arbitrary inventory sizes. + if ((assumeDefaultSize ? 9 : containerItemsWidth) != 9 || (assumeDefaultSize ? 3 : containerItemsHeight) != 3 || background.get() == Background.Flat) { + renderer.quad(x, y, w, h, color); + } else { + renderer.texture(background.get() == Background.Texture ? TEXTURE : TEXTURE_TRANSPARENT, x, y, w, h, color); + } + /* switch (background.get()) { case Texture, Outline -> renderer.texture(background.get() == Background.Texture ? TEXTURE : TEXTURE_TRANSPARENT, x, y, w, h, color); case Flat -> renderer.quad(x, y, w, h, color); - } + } */ } private ItemStack getContainer() { @@ -126,6 +214,46 @@ private ItemStack getContainer() { return null; } + private enum SupportedSources { + None { + }, + Inventory { + @Override + public ArrayList getItems() { + if (mc.player == null) return new ArrayList<>(); + ArrayList result = new ArrayList<>(3 * 9); + for (int row = 0; row < 3; row++) { + for (int i = 0; i < 9; i++) { + result.add(mc.player.getInventory().getStack((row + 1) * 9 + i)); + } + } + return result; + } + }, + Nametags { + @Override + public void configure() { + if (!Modules.get().get(Nametags.class).isActive()) Modules.get().get(Nametags.class).toggle(); + ((Set>) Modules.get().get(Nametags.class).settings.getGroup("General").get("entities").get()).add(EntityType.ITEM); + } + @Override + public ArrayList getItems() { return Modules.get().get(Nametags.class).getItems(); } + }, + ESP { + @Override + public void configure() { + if (!Modules.get().get(ESP.class).isActive()) Modules.get().get(ESP.class).toggle(); + ((Set>) Modules.get().get(ESP.class).settings.getGroup("General").get("entities").get()).add(EntityType.ITEM); + } + @Override + public ArrayList getItems() { return Modules.get().get(ESP.class).getItems(); } + }; + public void configure() {} + public ArrayList getItems() { + return new ArrayList<>(); + } + }; + public enum Background { None(162, 54), Texture(176, 67), diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/ESP.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/ESP.java index 40e8f3eb35..8e5b4a0374 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/ESP.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/ESP.java @@ -7,6 +7,7 @@ import meteordevelopment.meteorclient.events.render.Render2DEvent; import meteordevelopment.meteorclient.events.render.Render3DEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.renderer.Renderer2D; import meteordevelopment.meteorclient.renderer.ShapeMode; import meteordevelopment.meteorclient.settings.*; @@ -14,6 +15,7 @@ import meteordevelopment.meteorclient.systems.friends.Friends; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.utils.entity.EntityUtils; import meteordevelopment.meteorclient.utils.player.PlayerUtils; import meteordevelopment.meteorclient.utils.render.NametagUtils; @@ -23,11 +25,19 @@ import meteordevelopment.orbit.EventHandler; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; +import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.util.math.Box; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import org.joml.Vector3d; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; import java.util.Set; public class ESP extends Module { @@ -105,6 +115,13 @@ public class ESP extends Module { .build() ); + private final Setting> ignoredItems = sgGeneral.add(new ItemListSetting.Builder() + .name("ignored-items") + .description("Items to ignore.") + .defaultValue(Items.AIR) + .build() + ); + // Colors public final Setting distance = sgColors.add(new BoolSetting.Builder() @@ -178,25 +195,38 @@ public class ESP extends Module { private final Vector3d pos2 = new Vector3d(); private final Vector3d pos = new Vector3d(); - private int count; + private final List entityList = new ArrayList<>(); public ESP() { super(Categories.Render, "esp", "Renders entities through walls."); } - // Box - @EventHandler - private void onRender3D(Render3DEvent event) { - if (mode.get() == Mode._2D) return; + private void onTick(TickEvent.Post event) { + entityList.clear(); - count = 0; + boolean freecamNotActive = !Modules.get().isActive(Freecam.class); + boolean notThirdPerson = mc.options.getPerspective().isFirstPerson(); + Vec3d cameraPos = mc.gameRenderer.getCamera().getPos(); for (Entity entity : mc.world.getEntities()) { + EntityType type = entity.getType(); if (shouldSkip(entity)) continue; + entityList.add(entity); + } + + entityList.sort(Comparator.comparing(e -> e.squaredDistanceTo(cameraPos))); + } + + // Box + + @EventHandler + private void onRender3D(Render3DEvent event) { + if (mode.get() == Mode._2D) return; + + for (Entity entity : entityList) { if (mode.get() == Mode.Box || mode.get() == Mode.Wireframe) drawBoundingBox(event, entity); - count++; } } @@ -226,11 +256,8 @@ private void onRender2D(Render2DEvent event) { if (mode.get() != Mode._2D) return; Renderer2D.COLOR.begin(); - count = 0; - - for (Entity entity : mc.world.getEntities()) { - if (shouldSkip(entity)) continue; + for (Entity entity : entityList) { Box box = entity.getBoundingBox(); double x = MathHelper.lerp(event.tickDelta, entity.lastRenderX, entity.getX()) - entity.getX(); @@ -271,8 +298,6 @@ private void onRender2D(Render2DEvent event) { Renderer2D.COLOR.line(pos1.x, pos1.y, pos2.x, pos1.y, lineColor); Renderer2D.COLOR.line(pos1.x, pos2.y, pos2.x, pos2.y, lineColor); } - - count++; } Renderer2D.COLOR.render(null); @@ -301,6 +326,7 @@ public boolean shouldSkip(Entity entity) { if (!entities.get().contains(entity.getType())) return true; if (entity == mc.player && ignoreSelf.get()) return true; if (entity == mc.cameraEntity && mc.options.getPerspective().isFirstPerson()) return true; + if (entity.getType() == EntityType.ITEM && ignoredItems.get().contains(((ItemEntity) entity).getStack().getItem())) return true; return !EntityUtils.isInRenderDistance(entity); } @@ -343,7 +369,7 @@ public Color getEntityTypeColor(Entity entity) { @Override public String getInfoString() { - return Integer.toString(count); + return Integer.toString(entityList.size()); } public boolean isShader() { @@ -366,4 +392,19 @@ public String toString() { return this == _2D ? "2D" : super.toString(); } } + + public ArrayList getItems() { + ArrayList items = new ArrayList<>(); + + for (Entity entity : entityList) { + EntityType type = entity.getType(); + if (type == EntityType.ITEM && !ignoredItems.get().contains(((ItemEntity) entity).getStack().getItem())) { + items.add(((ItemEntity) entity).getStack()); + } + } + + items.sort(Comparator.comparing((ItemStack itemStack) -> itemStack.getName().getString()) + .thenComparing(Comparator.comparingInt(ItemStack::getCount).reversed())); + return items; + } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/Nametags.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/Nametags.java index 2057f9009a..340372bf15 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/render/Nametags.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/render/Nametags.java @@ -35,7 +35,9 @@ import net.minecraft.entity.*; import net.minecraft.entity.decoration.ItemFrameEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.tag.EnchantmentTags; @@ -61,6 +63,13 @@ public class Nametags extends Module { .build() ); + private final Setting> ignoredItems = sgGeneral.add(new ItemListSetting.Builder() + .name("ignored-items") + .description("Items to ignore.") + .defaultValue(Items.AIR) + .build() + ); + private final Setting scale = sgGeneral.add(new DoubleSetting.Builder() .name("scale") .description("The scale of the nametag.") @@ -228,7 +237,7 @@ public class Nametags extends Module { .build() ); - //Items + // Items private final Setting itemCount = sgItems.add(new BoolSetting.Builder() .name("show-count") @@ -331,6 +340,7 @@ private void onTick(TickEvent.Post event) { if (EntityUtils.getGameMode((PlayerEntity) entity) == null && ignoreBots.get()) continue; if (Friends.get().isFriend((PlayerEntity) entity) && ignoreFriends.get()) continue; } + if (type == EntityType.ITEM && ignoredItems.get().contains(((ItemEntity) entity).getStack().getItem())) continue; if (!culling.get() || PlayerUtils.isWithinCamera(entity, maxCullRange.get())) { entityList.add(entity); @@ -356,8 +366,7 @@ private void onRender2D(Render2DEvent event) { if (NametagUtils.to2D(pos, scale.get())) { if (type == EntityType.PLAYER) renderNametagPlayer(event, (PlayerEntity) entity, shadow); else if (type == EntityType.ITEM) renderNametagItem(((ItemEntity) entity).getStack(), shadow); - else if (type == EntityType.ITEM_FRAME) - renderNametagItem(((ItemFrameEntity) entity).getHeldItemStack(), shadow); + else if (type == EntityType.ITEM_FRAME) renderNametagItem(((ItemFrameEntity) entity).getHeldItemStack(), shadow); else if (type == EntityType.TNT) renderTntNametag((TntEntity) entity, shadow); else if (entity instanceof LivingEntity) renderGenericNametag((LivingEntity) entity, shadow); } @@ -708,4 +717,21 @@ public boolean excludeBots() { public boolean playerNametags() { return isActive() && entities.get().contains(EntityType.PLAYER); } + + public ArrayList getItems() { + int count = getRenderCount(); + ArrayList items = new ArrayList<>(); + + for (int i = count - 1; i > -1; i--) { + Entity entity = entityList.get(i); + EntityType type = entity.getType(); + if (type == EntityType.ITEM) { + items.add(((ItemEntity) entity).getStack()); + } + } + + items.sort(Comparator.comparing((ItemStack itemStack) -> itemStack.getName().getString()) + .thenComparing(Comparator.comparingInt(ItemStack::getCount).reversed())); + return items; + } }