-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
TheElenium: BLockESP: Added support for NBT-Data filtering #5933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,68 +25,106 @@ | |
| import net.minecraft.util.math.ChunkPos; | ||
| import net.minecraft.world.chunk.Chunk; | ||
| import net.minecraft.world.dimension.DimensionType; | ||
| import net.minecraft.block.BlockState; | ||
| import net.minecraft.state.property.Property; | ||
|
|
||
| import java.util.Iterator; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Set; | ||
| import java.util.concurrent.ExecutorService; | ||
| import java.util.concurrent.Executors; | ||
| import java.util.HashMap; | ||
| import java.util.Optional; | ||
|
|
||
| public class BlockESP extends Module { | ||
| private final SettingGroup sgGeneral = settings.getDefaultGroup(); | ||
|
|
||
| // General | ||
|
|
||
| private final Setting<List<Block>> blocks = sgGeneral.add(new BlockListSetting.Builder() | ||
| .name("blocks") | ||
| .description("Blocks to search for.") | ||
| .onChanged(blocks1 -> { | ||
| if (isActive() && Utils.canUpdate()) onActivate(); | ||
| }) | ||
| .build() | ||
| private final Setting<List<Block>> blocks = sgGeneral.add( | ||
| new BlockListSetting.Builder() | ||
| .name("blocks") | ||
| .description("Blocks to search for.") | ||
| .onChanged(blocks1 -> { | ||
| if (isActive() && Utils.canUpdate()) onActivate(); | ||
| }) | ||
| .build() | ||
| ); | ||
|
|
||
| private final Setting<ESPBlockData> defaultBlockConfig = sgGeneral.add(new GenericSetting.Builder<ESPBlockData>() | ||
| .name("default-block-config") | ||
| .description("Default block config.") | ||
| .defaultValue( | ||
| new ESPBlockData( | ||
| ShapeMode.Lines, | ||
| new SettingColor(0, 255, 200), | ||
| new SettingColor(0, 255, 200, 25), | ||
| true, | ||
| new SettingColor(0, 255, 200, 125) | ||
|
|
||
| // uncomment if NBT-Data should apply to all blocks !!! UNTESTED !!! | ||
|
|
||
| /* | ||
| private final Setting<List<String>> customFilters = sgGeneral.add( | ||
| new StringListSetting.Builder() | ||
| .name("NTB-Data") | ||
| .description( | ||
| "Filters with ntbdata (e.g. 'waterlogged=true')." | ||
| ) | ||
| ) | ||
| .build() | ||
| .defaultValue(new ArrayList<>()) | ||
| .onChanged(this::parseFilters) | ||
| .build() | ||
| ); | ||
|
|
||
| private final Setting<Map<Block, ESPBlockData>> blockConfigs = sgGeneral.add(new BlockDataSetting.Builder<ESPBlockData>() | ||
| .name("block-configs") | ||
| .description("Config for each block.") | ||
| .defaultData(defaultBlockConfig) | ||
| .build() | ||
| */ | ||
|
|
||
| private final Setting<ESPBlockData> defaultBlockConfig = sgGeneral.add( | ||
| new GenericSetting.Builder<ESPBlockData>() | ||
| .name("default-block-config") | ||
| .description("Default block config.") | ||
| .defaultValue( | ||
| new ESPBlockData( | ||
| ShapeMode.Lines, | ||
| new SettingColor(0, 255, 200), | ||
| new SettingColor(0, 255, 200, 25), | ||
| true, | ||
| new SettingColor(0, 255, 200, 125) | ||
| ) | ||
| ) | ||
| .build() | ||
| ); | ||
|
|
||
| private final Setting<Boolean> tracers = sgGeneral.add(new BoolSetting.Builder() | ||
| .name("tracers") | ||
| .description("Render tracer lines.") | ||
| .defaultValue(false) | ||
| .build() | ||
| private final Setting<Map<Block, ESPBlockData>> blockConfigs = | ||
| sgGeneral.add( | ||
| new BlockDataSetting.Builder<ESPBlockData>() | ||
| .name("block-configs") | ||
| .description("Config for each block.") | ||
| .defaultData(defaultBlockConfig) | ||
| .onChanged(configs -> { | ||
| if (isActive() && Utils.canUpdate()) onActivate(); | ||
| }) | ||
| .build() | ||
| ); | ||
|
|
||
| private final Setting<Boolean> tracers = sgGeneral.add( | ||
| new BoolSetting.Builder() | ||
| .name("tracers") | ||
| .description("Render tracer lines.") | ||
| .defaultValue(false) | ||
| .build() | ||
| ); | ||
|
|
||
| private final BlockPos.Mutable blockPos = new BlockPos.Mutable(); | ||
|
|
||
| private final Long2ObjectMap<ESPChunk> chunks = new Long2ObjectOpenHashMap<>(); | ||
| private final Map< | ||
| Block, | ||
| Map<Property<?>, Comparable<?>> | ||
| > activeFilterCache = new HashMap<>(); | ||
|
|
||
| private final Long2ObjectMap<ESPChunk> chunks = | ||
| new Long2ObjectOpenHashMap<>(); | ||
| private final Set<ESPGroup> groups = new ReferenceOpenHashSet<>(); | ||
| private final ExecutorService workerThread = Executors.newSingleThreadExecutor(); | ||
| private final ExecutorService workerThread = | ||
| Executors.newSingleThreadExecutor(); | ||
|
|
||
| private DimensionType lastDimension; | ||
|
|
||
| public BlockESP() { | ||
| super(Categories.Render, "block-esp", "Renders specified blocks through walls.", "search"); | ||
|
|
||
| super( | ||
| Categories.Render, | ||
| "block-esp", | ||
| "Renders specified blocks through walls.", | ||
| "search" | ||
| ); | ||
| RainbowColors.register(this::onTickRainbow); | ||
| } | ||
|
|
||
|
|
@@ -161,8 +199,7 @@ private void onChunkData(ChunkDataEvent event) { | |
| private void searchChunk(Chunk chunk) { | ||
| workerThread.submit(() -> { | ||
| if (!isActive()) return; | ||
| ESPChunk schunk = ESPChunk.searchChunk(chunk, blocks.get()); | ||
|
|
||
| ESPChunk schunk = ESPChunk.searchChunk(chunk, this); | ||
| if (schunk.size() > 0) { | ||
| synchronized (chunks) { | ||
| chunks.put(chunk.getPos().toLong(), schunk); | ||
|
|
@@ -189,8 +226,8 @@ private void onBlockUpdate(BlockUpdateEvent event) { | |
| int chunkZ = bz >> 4; | ||
| long key = ChunkPos.toLong(chunkX, chunkZ); | ||
|
|
||
| boolean added = blocks.get().contains(event.newState.getBlock()) && !blocks.get().contains(event.oldState.getBlock()); | ||
| boolean removed = !added && !blocks.get().contains(event.newState.getBlock()) && blocks.get().contains(event.oldState.getBlock()); | ||
| boolean added = shouldRender(event.newState) && !shouldRender(event.oldState); | ||
| boolean removed = !added && !shouldRender(event.newState) && shouldRender(event.oldState); | ||
|
|
||
| if (added || removed) { | ||
| workerThread.submit(() -> { | ||
|
|
@@ -263,4 +300,56 @@ private void onRender(Render3DEvent event) { | |
| public String getInfoString() { | ||
| return "%s groups".formatted(groups.size()); | ||
| } | ||
|
|
||
|
|
||
| public boolean shouldRender(BlockState state) { | ||
| Block block = state.getBlock(); | ||
|
|
||
| if (blocks.get().contains(block)) { | ||
| ESPBlockData blockData = blockConfigs.get().get(block); | ||
| if (blockData != null && !blockData.stateFilters.isEmpty()) { | ||
| return matchesStateFilters(state, block, blockData.stateFilters); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| // Check global state filters | ||
| if (activeFilterCache.containsKey(block)) { | ||
| Map<Property<?>, Comparable<?>> requiredProps = activeFilterCache.get(block); | ||
| for (Map.Entry<Property<?>,Comparable<?>> entry : requiredProps.entrySet()) { | ||
| if (!state.get(entry.getKey()).equals(entry.getValue())) { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| private boolean matchesStateFilters(BlockState state, Block block, List<String> filters) { | ||
| for (String filter : filters) { | ||
| try { | ||
| // Parse "key=value" format | ||
| String[] kv = filter.split("="); | ||
| if (kv.length != 2) continue; | ||
|
|
||
| String propertyName = kv[0].trim(); | ||
| String expectedValue = kv[1].trim(); | ||
|
|
||
| Property<?> property = block.getStateManager().getProperty(propertyName); | ||
| if (property == null) continue; | ||
|
|
||
| Optional<?> parsedValue = property.parse(expectedValue); | ||
| if (parsedValue.isEmpty()) continue; | ||
|
|
||
| if (!state.get(property).equals(parsedValue.get())) { | ||
| return false; | ||
| } | ||
| } catch (Exception e) { | ||
| // Invalid filter format | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a hot method, parsing should be done ahead of time |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,10 @@ | |
|
|
||
| package meteordevelopment.meteorclient.systems.modules.render.blockesp; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
|
|
||
| import meteordevelopment.meteorclient.gui.GuiTheme; | ||
| import meteordevelopment.meteorclient.gui.WidgetScreen; | ||
| import meteordevelopment.meteorclient.renderer.ShapeMode; | ||
|
|
@@ -16,6 +20,8 @@ | |
| import meteordevelopment.meteorclient.utils.render.color.SettingColor; | ||
| import net.minecraft.block.Block; | ||
| import net.minecraft.nbt.NbtCompound; | ||
| import net.minecraft.nbt.NbtList; | ||
| import net.minecraft.nbt.NbtString; | ||
|
|
||
| public class ESPBlockData implements IGeneric<ESPBlockData>, IChangeable, IBlockData<ESPBlockData> { | ||
| public ShapeMode shapeMode; | ||
|
|
@@ -25,6 +31,8 @@ public class ESPBlockData implements IGeneric<ESPBlockData>, IChangeable, IBlock | |
| public boolean tracer; | ||
| public SettingColor tracerColor; | ||
|
|
||
| public List<String> stateFilters = new ArrayList<>(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be |
||
|
|
||
| private boolean changed; | ||
|
|
||
| public ESPBlockData(ShapeMode shapeMode, SettingColor lineColor, SettingColor sideColor, boolean tracer, SettingColor tracerColor) { | ||
|
|
@@ -70,14 +78,19 @@ public ESPBlockData set(ESPBlockData value) { | |
| tracer = value.tracer; | ||
| tracerColor.set(value.tracerColor); | ||
|
|
||
| stateFilters.clear(); | ||
| stateFilters.addAll(value.stateFilters); | ||
|
|
||
| changed = value.changed; | ||
|
|
||
| return this; | ||
| } | ||
|
|
||
| @Override | ||
| public ESPBlockData copy() { | ||
| return new ESPBlockData(shapeMode, new SettingColor(lineColor), new SettingColor(sideColor), tracer, new SettingColor(tracerColor)); | ||
| ESPBlockData copy = new ESPBlockData(shapeMode, new SettingColor(lineColor), new SettingColor(sideColor), tracer, new SettingColor(tracerColor)); | ||
| copy.stateFilters.addAll(stateFilters); | ||
| return copy; | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -91,6 +104,12 @@ public NbtCompound toTag() { | |
| tag.putBoolean("tracer", tracer); | ||
| tag.put("tracerColor", tracerColor.toTag()); | ||
|
|
||
| NbtList filtersList = new NbtList(); | ||
| for (String filter : stateFilters) { | ||
| filtersList.add(NbtString.of(filter)); | ||
| } | ||
| tag.put("NBT-Data", filtersList); | ||
|
|
||
| tag.putBoolean("changed", changed); | ||
|
|
||
| return tag; | ||
|
|
@@ -105,6 +124,14 @@ public ESPBlockData fromTag(NbtCompound tag) { | |
| tracer = tag.getBoolean("tracer", false); | ||
| tracerColor.fromTag(tag.getCompoundOrEmpty("tracerColor")); | ||
|
|
||
| stateFilters.clear(); | ||
| tag.getList("NBT-Data").ifPresent(filtersList -> { | ||
| for (int i = 0; i < filtersList.size(); i++) { | ||
| filtersList.getString(i).ifPresent(stateFilters::add); | ||
| } | ||
| }); | ||
|
|
||
|
|
||
| changed = tag.getBoolean("changed", false); | ||
|
|
||
| return this; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,8 @@ | |
| import net.minecraft.block.Block; | ||
| import org.jetbrains.annotations.Nullable; | ||
|
|
||
| import java.util.ArrayList; | ||
|
|
||
| public class ESPBlockDataScreen extends WindowScreen { | ||
| private final ESPBlockData blockData; | ||
| private final Setting<?> setting; | ||
|
|
@@ -39,6 +41,7 @@ public void initWidgets() { | |
| Settings settings = new Settings(); | ||
| SettingGroup sgGeneral = settings.getDefaultGroup(); | ||
| SettingGroup sgTracer = settings.createGroup("Tracer"); | ||
| SettingGroup sgFilters = settings.createGroup("NBT-Data"); | ||
|
|
||
| sgGeneral.add(new EnumSetting.Builder<ShapeMode>() | ||
| .name("shape-mode") | ||
|
|
@@ -110,6 +113,20 @@ public void initWidgets() { | |
| .build() | ||
| ); | ||
|
|
||
| // Add state filters setting | ||
| sgFilters.add(new StringListSetting.Builder() | ||
| .name("NBT-Data") | ||
| .description("Filters with states (e.g. 'waterlogged=false', 'facing=north', 'ominous=true'). Only blocks matching ALL filters will be shown.") | ||
| .defaultValue(new ArrayList<>()) | ||
| .onModuleActivated(stringSetting -> stringSetting.set(blockData.stateFilters)) | ||
| .onChanged(filters -> { | ||
| blockData.stateFilters.clear(); | ||
| blockData.stateFilters.addAll(filters); | ||
| onChanged(); | ||
| }) | ||
| .build() | ||
| ); | ||
|
Comment on lines
+117
to
+128
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. imho using a string list for this is super unintuitive, it should be a separate setting type |
||
|
|
||
| settings.onActivated(); | ||
| add(theme.settings(settings)).expandX(); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this map is always empty