Skip to content

Commit f8fb17e

Browse files
committed
TheElenium: BLockESP: Added support for NBT-Data filtering
1 parent f599a6a commit f8fb17e

File tree

5 files changed

+179
-43
lines changed

5 files changed

+179
-43
lines changed

src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/BlockESP.java

Lines changed: 128 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -25,68 +25,106 @@
2525
import net.minecraft.util.math.ChunkPos;
2626
import net.minecraft.world.chunk.Chunk;
2727
import net.minecraft.world.dimension.DimensionType;
28+
import net.minecraft.block.BlockState;
29+
import net.minecraft.state.property.Property;
2830

2931
import java.util.Iterator;
3032
import java.util.List;
3133
import java.util.Map;
3234
import java.util.Set;
3335
import java.util.concurrent.ExecutorService;
3436
import java.util.concurrent.Executors;
37+
import java.util.HashMap;
38+
import java.util.Optional;
3539

3640
public class BlockESP extends Module {
3741
private final SettingGroup sgGeneral = settings.getDefaultGroup();
3842

3943
// General
4044

41-
private final Setting<List<Block>> blocks = sgGeneral.add(new BlockListSetting.Builder()
42-
.name("blocks")
43-
.description("Blocks to search for.")
44-
.onChanged(blocks1 -> {
45-
if (isActive() && Utils.canUpdate()) onActivate();
46-
})
47-
.build()
45+
private final Setting<List<Block>> blocks = sgGeneral.add(
46+
new BlockListSetting.Builder()
47+
.name("blocks")
48+
.description("Blocks to search for.")
49+
.onChanged(blocks1 -> {
50+
if (isActive() && Utils.canUpdate()) onActivate();
51+
})
52+
.build()
4853
);
49-
50-
private final Setting<ESPBlockData> defaultBlockConfig = sgGeneral.add(new GenericSetting.Builder<ESPBlockData>()
51-
.name("default-block-config")
52-
.description("Default block config.")
53-
.defaultValue(
54-
new ESPBlockData(
55-
ShapeMode.Lines,
56-
new SettingColor(0, 255, 200),
57-
new SettingColor(0, 255, 200, 25),
58-
true,
59-
new SettingColor(0, 255, 200, 125)
54+
55+
// uncomment if NBT-Data should apply to all blocks !!! UNTESTED !!!
56+
57+
/*
58+
private final Setting<List<String>> customFilters = sgGeneral.add(
59+
new StringListSetting.Builder()
60+
.name("NTB-Data")
61+
.description(
62+
"Filters with ntbdata (e.g. 'waterlogged=true')."
6063
)
61-
)
62-
.build()
64+
.defaultValue(new ArrayList<>())
65+
.onChanged(this::parseFilters)
66+
.build()
6367
);
64-
65-
private final Setting<Map<Block, ESPBlockData>> blockConfigs = sgGeneral.add(new BlockDataSetting.Builder<ESPBlockData>()
66-
.name("block-configs")
67-
.description("Config for each block.")
68-
.defaultData(defaultBlockConfig)
69-
.build()
68+
*/
69+
70+
private final Setting<ESPBlockData> defaultBlockConfig = sgGeneral.add(
71+
new GenericSetting.Builder<ESPBlockData>()
72+
.name("default-block-config")
73+
.description("Default block config.")
74+
.defaultValue(
75+
new ESPBlockData(
76+
ShapeMode.Lines,
77+
new SettingColor(0, 255, 200),
78+
new SettingColor(0, 255, 200, 25),
79+
true,
80+
new SettingColor(0, 255, 200, 125)
81+
)
82+
)
83+
.build()
7084
);
7185

72-
private final Setting<Boolean> tracers = sgGeneral.add(new BoolSetting.Builder()
73-
.name("tracers")
74-
.description("Render tracer lines.")
75-
.defaultValue(false)
76-
.build()
86+
private final Setting<Map<Block, ESPBlockData>> blockConfigs =
87+
sgGeneral.add(
88+
new BlockDataSetting.Builder<ESPBlockData>()
89+
.name("block-configs")
90+
.description("Config for each block.")
91+
.defaultData(defaultBlockConfig)
92+
.onChanged(configs -> {
93+
if (isActive() && Utils.canUpdate()) onActivate();
94+
})
95+
.build()
96+
);
97+
98+
private final Setting<Boolean> tracers = sgGeneral.add(
99+
new BoolSetting.Builder()
100+
.name("tracers")
101+
.description("Render tracer lines.")
102+
.defaultValue(false)
103+
.build()
77104
);
78105

79106
private final BlockPos.Mutable blockPos = new BlockPos.Mutable();
80107

81-
private final Long2ObjectMap<ESPChunk> chunks = new Long2ObjectOpenHashMap<>();
108+
private final Map<
109+
Block,
110+
Map<Property<?>, Comparable<?>>
111+
> activeFilterCache = new HashMap<>();
112+
113+
private final Long2ObjectMap<ESPChunk> chunks =
114+
new Long2ObjectOpenHashMap<>();
82115
private final Set<ESPGroup> groups = new ReferenceOpenHashSet<>();
83-
private final ExecutorService workerThread = Executors.newSingleThreadExecutor();
116+
private final ExecutorService workerThread =
117+
Executors.newSingleThreadExecutor();
84118

85119
private DimensionType lastDimension;
86120

87121
public BlockESP() {
88-
super(Categories.Render, "block-esp", "Renders specified blocks through walls.", "search");
89-
122+
super(
123+
Categories.Render,
124+
"block-esp",
125+
"Renders specified blocks through walls.",
126+
"search"
127+
);
90128
RainbowColors.register(this::onTickRainbow);
91129
}
92130

@@ -161,8 +199,7 @@ private void onChunkData(ChunkDataEvent event) {
161199
private void searchChunk(Chunk chunk) {
162200
workerThread.submit(() -> {
163201
if (!isActive()) return;
164-
ESPChunk schunk = ESPChunk.searchChunk(chunk, blocks.get());
165-
202+
ESPChunk schunk = ESPChunk.searchChunk(chunk, this);
166203
if (schunk.size() > 0) {
167204
synchronized (chunks) {
168205
chunks.put(chunk.getPos().toLong(), schunk);
@@ -189,8 +226,8 @@ private void onBlockUpdate(BlockUpdateEvent event) {
189226
int chunkZ = bz >> 4;
190227
long key = ChunkPos.toLong(chunkX, chunkZ);
191228

192-
boolean added = blocks.get().contains(event.newState.getBlock()) && !blocks.get().contains(event.oldState.getBlock());
193-
boolean removed = !added && !blocks.get().contains(event.newState.getBlock()) && blocks.get().contains(event.oldState.getBlock());
229+
boolean added = shouldRender(event.newState) && !shouldRender(event.oldState);
230+
boolean removed = !added && !shouldRender(event.newState) && shouldRender(event.oldState);
194231

195232
if (added || removed) {
196233
workerThread.submit(() -> {
@@ -263,4 +300,56 @@ private void onRender(Render3DEvent event) {
263300
public String getInfoString() {
264301
return "%s groups".formatted(groups.size());
265302
}
303+
304+
305+
public boolean shouldRender(BlockState state) {
306+
Block block = state.getBlock();
307+
308+
if (blocks.get().contains(block)) {
309+
ESPBlockData blockData = blockConfigs.get().get(block);
310+
if (blockData != null && !blockData.stateFilters.isEmpty()) {
311+
return matchesStateFilters(state, block, blockData.stateFilters);
312+
}
313+
return true;
314+
}
315+
316+
// Check global state filters
317+
if (activeFilterCache.containsKey(block)) {
318+
Map<Property<?>, Comparable<?>> requiredProps = activeFilterCache.get(block);
319+
for (Map.Entry<Property<?>,Comparable<?>> entry : requiredProps.entrySet()) {
320+
if (!state.get(entry.getKey()).equals(entry.getValue())) {
321+
return false;
322+
}
323+
}
324+
return true;
325+
}
326+
return false;
327+
}
328+
329+
private boolean matchesStateFilters(BlockState state, Block block, List<String> filters) {
330+
for (String filter : filters) {
331+
try {
332+
// Parse "key=value" format
333+
String[] kv = filter.split("=");
334+
if (kv.length != 2) continue;
335+
336+
String propertyName = kv[0].trim();
337+
String expectedValue = kv[1].trim();
338+
339+
Property<?> property = block.getStateManager().getProperty(propertyName);
340+
if (property == null) continue;
341+
342+
Optional<?> parsedValue = property.parse(expectedValue);
343+
if (parsedValue.isEmpty()) continue;
344+
345+
if (!state.get(property).equals(parsedValue.get())) {
346+
return false;
347+
}
348+
} catch (Exception e) {
349+
// Invalid filter format
350+
}
351+
}
352+
353+
return true;
354+
}
266355
}

src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPBlock.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ private boolean isNeighbour(Direction dir) {
127127

128128
if (neighbourState.getBlock() != state.getBlock()) return false;
129129

130+
if (!blockEsp.shouldRender(neighbourState)) return false;
131+
130132
VoxelShape cube = VoxelShapes.fullCube();
131133
VoxelShape shape = state.getOutlineShape(mc.world, blockPos);
132134
VoxelShape neighbourShape = neighbourState.getOutlineShape(mc.world, blockPos);
@@ -165,7 +167,8 @@ private boolean isNeighbour(Direction dir) {
165167

166168
private boolean isNeighbourDiagonal(double x, double y, double z) {
167169
blockPos.set(this.x + x, this.y + y, this.z + z);
168-
return state.getBlock() == mc.world.getBlockState(blockPos).getBlock();
170+
BlockState neighbourState = mc.world.getBlockState(blockPos);
171+
return state.getBlock() == neighbourState.getBlock() && blockEsp.shouldRender(neighbourState);
169172
}
170173

171174
public void render(Render3DEvent event) {

src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPBlockData.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
package meteordevelopment.meteorclient.systems.modules.render.blockesp;
77

8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
812
import meteordevelopment.meteorclient.gui.GuiTheme;
913
import meteordevelopment.meteorclient.gui.WidgetScreen;
1014
import meteordevelopment.meteorclient.renderer.ShapeMode;
@@ -16,6 +20,8 @@
1620
import meteordevelopment.meteorclient.utils.render.color.SettingColor;
1721
import net.minecraft.block.Block;
1822
import net.minecraft.nbt.NbtCompound;
23+
import net.minecraft.nbt.NbtList;
24+
import net.minecraft.nbt.NbtString;
1925

2026
public class ESPBlockData implements IGeneric<ESPBlockData>, IChangeable, IBlockData<ESPBlockData> {
2127
public ShapeMode shapeMode;
@@ -25,6 +31,8 @@ public class ESPBlockData implements IGeneric<ESPBlockData>, IChangeable, IBlock
2531
public boolean tracer;
2632
public SettingColor tracerColor;
2733

34+
public List<String> stateFilters = new ArrayList<>();
35+
2836
private boolean changed;
2937

3038
public ESPBlockData(ShapeMode shapeMode, SettingColor lineColor, SettingColor sideColor, boolean tracer, SettingColor tracerColor) {
@@ -70,14 +78,19 @@ public ESPBlockData set(ESPBlockData value) {
7078
tracer = value.tracer;
7179
tracerColor.set(value.tracerColor);
7280

81+
stateFilters.clear();
82+
stateFilters.addAll(value.stateFilters);
83+
7384
changed = value.changed;
7485

7586
return this;
7687
}
7788

7889
@Override
7990
public ESPBlockData copy() {
80-
return new ESPBlockData(shapeMode, new SettingColor(lineColor), new SettingColor(sideColor), tracer, new SettingColor(tracerColor));
91+
ESPBlockData copy = new ESPBlockData(shapeMode, new SettingColor(lineColor), new SettingColor(sideColor), tracer, new SettingColor(tracerColor));
92+
copy.stateFilters.addAll(stateFilters);
93+
return copy;
8194
}
8295

8396
@Override
@@ -91,6 +104,12 @@ public NbtCompound toTag() {
91104
tag.putBoolean("tracer", tracer);
92105
tag.put("tracerColor", tracerColor.toTag());
93106

107+
NbtList filtersList = new NbtList();
108+
for (String filter : stateFilters) {
109+
filtersList.add(NbtString.of(filter));
110+
}
111+
tag.put("NBT-Data", filtersList);
112+
94113
tag.putBoolean("changed", changed);
95114

96115
return tag;
@@ -105,6 +124,14 @@ public ESPBlockData fromTag(NbtCompound tag) {
105124
tracer = tag.getBoolean("tracer", false);
106125
tracerColor.fromTag(tag.getCompoundOrEmpty("tracerColor"));
107126

127+
stateFilters.clear();
128+
tag.getList("NBT-Data").ifPresent(filtersList -> {
129+
for (int i = 0; i < filtersList.size(); i++) {
130+
filtersList.getString(i).ifPresent(stateFilters::add);
131+
}
132+
});
133+
134+
108135
changed = tag.getBoolean("changed", false);
109136

110137
return this;

src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPBlockDataScreen.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import net.minecraft.block.Block;
1414
import org.jetbrains.annotations.Nullable;
1515

16+
import java.util.ArrayList;
17+
1618
public class ESPBlockDataScreen extends WindowScreen {
1719
private final ESPBlockData blockData;
1820
private final Setting<?> setting;
@@ -39,6 +41,7 @@ public void initWidgets() {
3941
Settings settings = new Settings();
4042
SettingGroup sgGeneral = settings.getDefaultGroup();
4143
SettingGroup sgTracer = settings.createGroup("Tracer");
44+
SettingGroup sgFilters = settings.createGroup("NBT-Data");
4245

4346
sgGeneral.add(new EnumSetting.Builder<ShapeMode>()
4447
.name("shape-mode")
@@ -110,6 +113,20 @@ public void initWidgets() {
110113
.build()
111114
);
112115

116+
// Add state filters setting
117+
sgFilters.add(new StringListSetting.Builder()
118+
.name("NBT-Data")
119+
.description("Filters with states (e.g. 'waterlogged=false', 'facing=north', 'ominous=true'). Only blocks matching ALL filters will be shown.")
120+
.defaultValue(new ArrayList<>())
121+
.onModuleActivated(stringSetting -> stringSetting.set(blockData.stateFilters))
122+
.onChanged(filters -> {
123+
blockData.stateFilters.clear();
124+
blockData.stateFilters.addAll(filters);
125+
onChanged();
126+
})
127+
.build()
128+
);
129+
113130
settings.onActivated();
114131
add(theme.settings(settings)).expandX();
115132
}

src/main/java/meteordevelopment/meteorclient/systems/modules/render/blockesp/ESPChunk.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public void render(Render3DEvent event) {
8686
}
8787

8888

89-
public static ESPChunk searchChunk(Chunk chunk, List<Block> blocks) {
89+
public static ESPChunk searchChunk(Chunk chunk, BlockESP module) {
9090
ESPChunk schunk = new ESPChunk(chunk.getPos().x, chunk.getPos().z);
9191
if (schunk.shouldBeDeleted()) return schunk;
9292

@@ -100,7 +100,7 @@ public static ESPChunk searchChunk(Chunk chunk, List<Block> blocks) {
100100
blockPos.set(x, y, z);
101101
BlockState bs = chunk.getBlockState(blockPos);
102102

103-
if (blocks.contains(bs.getBlock())) schunk.add(blockPos, false);
103+
if (module.shouldRender(bs)) schunk.add(blockPos, false);
104104
}
105105
}
106106
}

0 commit comments

Comments
 (0)